HTTP DELETE работает из браузера, но не из почтальона или приложения IOS - PullRequest
2 голосов
/ 13 июля 2020

При попытке HTTP-запроса к моему rest api я постоянно получаю ошибку 401 при использовании следующего кода. Я не получаю эту ошибку при запросе другого типа. Я предоставил функцию, которая выполняет запрос ниже.

func deleteEvent(id: Int){
        eventUrl.append(String(id))
       let request = NSMutableURLRequest(url: NSURL(string: eventUrl)! as URL)
        request.httpMethod = "DELETE"
        print(eventUrl)
        eventUrl.removeLast()
        print(self.token!)
        request.allHTTPHeaderFields = ["Authorization": "Token \(self.token)"]
        let task = URLSession.shared.dataTask(with: request as URLRequest) { data, response, error in
               
               
               if error != nil {
                   print("error=\(String(describing: error))")
                   //put variable that triggers error try again view here
                   return
               }
               
               print("response = \(String(describing: response))")
           }
           task.resume()

       }

При отправке запроса на удаление с помощью почтальона остальной api просто возвращает данные, которые я хочу удалить, но не удаляет их. Для справки, я опубликовал классы представлений и разрешений, связанные с этим запросом. Любая помощь в понимании того, почему это может привести к ошибке, приветствуется!

Views.py

class UserProfileFeedViewSet(viewsets.ModelViewSet):
    """Handles creating, reading and updating profile feed items"""
    authentication_classes = (TokenAuthentication,)
    serializer_class = serializers.ProfileFeedItemSerializer
    queryset = models.ProfileFeedItem.objects.all()
    permission_classes = (permissions.UpdateOwnStatus, IsAuthenticated)

    def perform_create(self, serializer):
        """Sets the user profile to the logged in user"""
        #
        serializer.save(user_profile=self.request.user)

Permissions.py

class UpdateOwnStatus(permissions.BasePermission):
    """Allow users to update their own status"""

    def has_object_permission(self, request, view, obj):
        """Check the user is trying to update their own status"""
        if request.method in permissions.SAFE_METHODS:
            return True

        return obj.user_profile.id == request.user.id

ЗАГОЛОВОК, ОТПРАВЛЕННЫЙ С ЗАПРОСОМ НА УДАЛЕНИЕ ЧЕРЕЗ ПОЧТУ ЗАГОЛОВОК ОТПРАВЛЕН С ЗАПРОСОМ НА УДАЛЕНИЕ ЧЕРЕЗ POSTMAN

1 Ответ

1 голос
/ 21 июля 2020

Предисловие: Вы упускаете слишком много важной информации из вопроса, чтобы на него можно было правильно ответить. Ваш код Swift выглядит, и, пожалуйста, не обижайтесь, немного новичок-i sh или как будто он был перенесен с Objective- C без особого опыта.

Я не знаю, почему POSTMAN не работает, но я вижу некоторые красные флажки в коде Swift, которые вы, возможно, захотите изучить, чтобы выяснить, почему ваше приложение iOS не работает.

Сначала я заметил, что eventUrl кажется String свойство типа, содержащего функцию deleteEvent. Вы изменяете его, добавляя событие id, создавая из него URL (как ни странно, см. Ниже), а затем снова изменяете его. Хотя это само по себе не обязательно неправильно, это может открыть двери для гоночных условий в зависимости от того, как ваше приложение работает в целом.

Что еще более важно: ваш eventUrl оканчивается на «/»? Я предполагаю, что ваша конечная точка DELETE имеет форму https://somedomain.com/some/path/<id>, верно? Теперь, если eventUrl просто содержит https://somedomain.com/some/path, ваш код создает https://somedomain.com/some/path<id>. Последний da sh отсутствует, что определенно сбивает ваш бэкэнд (как я не могу сказать, поскольку это зависит от того, как путь разрешен в вашем серверном приложении).

Трудно сказать, что еще происходит из из приложения iOS, но, кроме этой потенциальной ловушки, я бы действительно рекомендовал использовать правильные типы Swift, где это возможно. Вот очищенная версия вашего метода, надеюсь, это немного поможет вам при отладке:

func deleteEvent(id: Int) {
    guard let baseUrl = URL(string: eventUrl), let token = token else {
        // add more error handling code here and/or put a breakpoint here to inspect
        print("Could not create proper eventUrl or token is nil!")
        return
    }
    let deletionUrl = baseUrl.appendingPathComponent("\(id)")
    print("Deletion URL with appended id: \(deletionUrl.absoluteString)")

    var request = URLRequest(url: deletionUrl)
    request.httpMethod = "DELETE"
    print(token) // ensure this is correct
    request.allHTTPHeaderFields = ["Authorization": "Token \(token)"]
    let task = URLSession.shared.dataTask(with: request) { data, response, error in
        if let error = error {
            print("Encountered network error: \(error)")
            return
        }
        
        if let httpResponse = response as? HTTPURLResponse {
            // this is basically also debugging code
            print("Endpoint responded with status: \(httpResponse.statusCode)")
            print("                   with headers:\n\(httpResponse.allHeaderFields)")
        }
        // Debug output of the data:
        if let data = data {
            let payloadAsSimpleString = String(data: data, encoding: .utf8) ?? "(can't parse payload)"
            print("Response contains payload\n\(payloadAsSimpleString)")
        }
    }
    task.resume()
}

Очевидно, что это все еще ограничено с точки зрения обработки ошибок, et c., Но немного более быстрым и быстрым. содержит дополнительный вывод консоли, который, надеюсь, будет вам полезен. Последняя важная вещь: вы должны убедиться, что iOS не просто блокирует ваш запрос из-за Apple Transport Security : убедитесь, что ваш список содержит ожидаемые записи, если это необходимо (см. Также здесь для быстрого вступления).

...