Невозможно УДАЛИТЬ, когда работают POST, PUT и GET, AngularJS-CORS, Flask-CORS
Я в растерянности, я не могу понять, почему не приходят запросы DELETE, когда POST, PUT и GET работают просто отлично. И я почти уверен, что уже выполнил все необходимые настройки для работы CORS. Я использую расширение AngularJS и Flask-CORS
А вот моя текущая работа:
Angular Config:
angular.module('...' [...]).config(function($httpProvider) {
$httpProvider.defaults.useXDomain = true;
delete $httpProvider.defaults.headers.common['X-Requested-With'];
});
Угловая фабрика:
angular.module('...').factory('...'), function($http) {
return {
deleteElectronicAddress: function (partyId, contactMechanismId) {
return $http({
url: urlBase + 'party/' + partyId + '/contact-mechanism/' + contactMechanismId,
method: 'DELETE',
});
},
someMoreMethods: { ... }
}
}
Мои коды Flask (я использую предложенную структуру приложения Мигеля Гринберга в своей книге Flask Web Development)
config.py
class Config:
...
CORS_HEADERS = 'Content-Type'
CORS_RESOURCES = {r"/api/*": {"origins": "*"}}
CORS_METHODS = ['GET', 'POST', 'DELETE', 'PUT', 'OPTIONS', 'HEAD']
...
project_folder / приложение /__init__.py:
from flask import Flask
from flask.ext.sqlalchemy import SQLAlchemy
from flask.ext.cors import CORS
from config import config
db = SQLAlchemy()
def create_app(config_name):
app = Flask(__name__)
app.config.from_object(config[config_name])
config[config_name].init_app(app)
db.init_app(app)
CORS(app)
from .api_1_0 import api as api_1_0_blueprint
app.register_blueprint(api_1_0_blueprint, url_prefix='/api/v1.0')
return app
В настоящее время я использую Flask-CORS v1.7.4.
project_folder / приложение / API / party_contact_mechanisms.py:
from datetime import date
from flask import jsonify
from .. import db
from ..models import PartyContactMechanism
from . import api
@api.route(
'/party/<int:party_id>' +
'/contact-mechanism/<int:contact_mechanism>', methods=['DELETE'])
def unlink_party_contact_mechanism(party_id, contact_mechanism):
"""Unlink the contact mechanism onto the party."""
party_contact = PartyContactMechanism.query \
.filter_by(party_id=party_id) \
.filter_by(contact_mechanism_id=contact_mechanism) \
.first()
party_contact.thru_date = str(date.today())
db.session.commit()
return jsonify(success=True)
Я уже проверил это с httpie, как на моей локальной машине, так и на другой машине, подключенной к локальной сети, и она работает просто отлично.
Я использую как angular, так и флеш с конфигурацией хоста 0.0.0.0, чтобы он был доступен на других машинах, подключенных к сети.
Вот мои заголовки запроса и ответа при вызове из браузера
ЗАПРОСИТЬ ЗАГОЛОВОКИ:
OPTIONS /api/v1.0/party/32232/contact-mechanism/80667 HTTP/1.1
Host: 10.61.18.217:5000
User-Agent: Mozilla/5.0 (X11; Ubuntu; Linux x86_64; rv:31.0) Gecko/20100101 Firefox/31.0
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
Accept-Language: en-US,en;q=0.5
Accept-Encoding: gzip, deflate
Origin: http://0.0.0.0:9000
Access-Control-Request-Method: DELETE
Connection: keep-alive
ОТВЕТНЫЕ ЗАГОЛОВКИ:
HTTP/1.0 200 OK
Content-Type: text/html; charset=utf-8
Allow: POST, OPTIONS, DELETE
access-control-allow-origin: *
Access-Control-Allow-Methods: POST
Access-Control-Allow-Headers: Content-Type
Content-Length: 0
Server: Werkzeug/0.9.6 Python/2.7.6
Date: Mon, 18 Aug 2014 07:20:18 GMT
Вот заголовки запроса и ответа при вызове из httpie:
ЗАПРОСИТЬ ЗАГОЛОВОКИ:
DELETE /api/v1.0/party/32232/contact-mechanism/80667 HTTP/1.1
Accept: */*
Accept-Encoding: gzip, deflate, compress
Content-Length: 0
Host: 10.61.18.217:5000
User-Agent: HTTPie/0.8.0
ОТВЕТНЫЕ ЗАГОЛОВКИ:
HTTP/1.0 200 OK
Access-Control-Allow-Headers: Content-Type
Access-Control-Allow-Methods: DELETE, GET, HEAD, OPTIONS, POST, PUT
Access-Control-Allow-Origin: *
Content-Length: 21
Content-Type: application/json
Date: Mon, 18 Aug 2014 07:31:05 GMT
Server: Werkzeug/0.9.6 Python/2.7.6
{
"success": true
}
1 ответ
Я понял, что я делаю неправильно,
на самом деле есть еще один маршрут на моем project_folder/app/api/party_contact_mechanisms.py
файл, который я не потрудился добавить на мой образец, так как я думал, что он не имеет значения (ну, я ошибаюсь)
вот:
@api.route(
'/party/<int:party_id>' +
'/contact-mechanism/<int:contact_mechanism>',
methods=['POST'])
@cross_origin(methods=['POST'])
def link_party_contact_mechanism(party_id, contact_mechanism):
"""Link the contact mechanism onto the party."""
party_contact = PartyContactMechanism(
party_id=party_id, contact_mechanism=contact_mechanism,
from_date=str(date.today()), thru_date=None
)
db.session.add(party_contact)
db.session.commit()
return jsonify({})
как вы можете видеть, оно имеет то же правило маршрута, но с другим методом, здесь POST.
И до того, как я использовал Flask-CORS v1.7, я использовал v1.3, что объясняет @cross_origin
декоратор, так как это единственный способ сделать ваш маршрут включенным CORS (или, если вы хотите, чтобы он был на всех ваших маршрутах, вы помещаете его на свой before_request
)
То, что я пропустил в новой версии, так это то, что теперь вы можете активировать CORS всего своего приложения, инициализировав его, так же, как я это делал на своем project_folder/app/__init__.py
и да, вы все равно можете делать определенные маршруты через `@cross_origin', но когда вы это делаете, он перезаписывает глобальную конфигурацию, и в моем случае у меня есть два маршрута с одинаковым правилом, но разными методами, и только один с декоратором @cross_origin и в этом корень проблемы.
Я просто удалил его, и теперь он отлично работает. Будьте предупреждены, добавляя другой @cross_origin
Декоратор на вашем другом маршруте не исправит это, кажется, он читает только первое появление этого.