javascriptreactjsdjangodjango-rest-frameworkdj-rest-auth

When I upload image as base64 in post request I get error 403


When I try to upload an image to the backend using a form with post request, I get a 403 error. I tried adding X-CSRFToken and "Accept": "application/json" to the headers, it didn't help at all. I tried to add the owner to the postBody from the name that I was saving to the localstorage I don't know where I made a mistake. I use dj-rest-auth for authentication There is fetch function from frontend:

export async function action({ request }) { 
    const data = await request.formData();
    // const file = fileToBase64(data.get('file'))
    console.log(data)
    const postData = { 
      title: data.get('title'),
      image: data.get('base64File'),
    };
    console.log(postData)
    const response = await fetch('http://127.0.0.1:8000/posts', {
      method: 'POST',
      headers: {
        "Content-Type": "application/json"
      },
      body: JSON.stringify(postData),
    });
    if (response.status === 422 || response.status === 401) {
      
      return response;
    }
  
    if (!response.ok) {
      throw json({ message: 'Could not add image.' }, { status: 500 });
    }
  
    
    const resData = await response.json();
    console.log(resData)
    return redirect('/');
  }

There is backend serializer:

class PostsSerializer(serializers.HyperlinkedModelSerializer):
    title = serializers.CharField(max_length=60, )
    owner = serializers.ReadOnlyField(source='owner.username')
    # creator_id = UserSerializer(many=False, read_only=True).data
    favorites = serializers.HyperlinkedRelatedField(many=True, read_only=True, view_name='favorite-detail')
    comments = serializers.HyperlinkedRelatedField(many=True, read_only=True, view_name='comment-detail')

    class Meta:
        model = Post
        fields = ['pk', 'url', 'title', 'owner', 'image', 'created_at', 'favorites', 'comments']

And view:

class PostList(generics.ListCreateAPIView):

permission_classes = [permissions.IsAuthenticatedOrReadOnly, IsCurrentUserOwnerOrReadOnly]
queryset = Post.objects.all()
serializer_class = PostsSerializer
ordering_fields = ['created_at', 'favorites']
filter_fields = ['title']
search_fields = ['title']
name = 'post-list'

def perform_create(self, serializer):
    serializer.save(owner=self.request.user)

If you need the full code here is a link to the repository: https://github.com/Cichyy22/imagur-like-site


Solution

  • I solved the problem by editing the request:

     export async function action({ request }) { 
        const data = await request.formData();
        // const file = fileToBase64(data.get('file'))
        console.log(data)
        const postData = { 
          title: data.get('title'),
          image: data.get('base64File')
        };
        console.log(postData)
        const response = await fetch('http://127.0.0.1:8000/posts', {
          method: 'POST',
          headers: {
            'Authorization': 'Token ' + localStorage.getItem('token'),
            "X-CSRFToken": Cookies.get('csrftoken'),
            "Accept": "application/json",
            "Content-Type": "application/json"
          },
          body: JSON.stringify(postData),
        });
        if (response.status === 422 || response.status === 401) {
          
          return response;
        }
      
        if (!response.ok) {
          throw json({ message: 'Could not add image.' }, { status: 500 });
        }
      
        
        const resData = await response.json();
        console.log(resData)
        return redirect('/');
      }
    

    And by editing the settings file on the backend:

    REST_FRAMEWORK = {
        'DEFAULT_FILTER_BACKENDS': (
            'django_filters.rest_framework.DjangoFilterBackend',
            'rest_framework.filters.OrderingFilter',
            'rest_framework.filters.SearchFilter',
        ),
        'DEFAULT_AUTHENTICATION_CLASSES': (
            'rest_framework.authentication.TokenAuthentication',
            'rest_framework.authentication.SessionAuthentication',
        )
    }
    REST_USE_JWT = True 
    JWT_AUTH_COOKIE_USE_CSRF = True