Deployd - данные, полученные с помощью AngularJS CORS

В настоящее время я читаю "Pro AngularJS" Адама Фримена. Рассматривая примеры, он предлагает читателю создать приложение для спортивного магазина, используя Angular (конечно) с ресурсом сервера Deployd. Ресурс Deployd настроен так, чтобы возвращать данные JSON, которые должны быть заполнены в модели. Я использую NodeJS для запуска моего сервера. В настоящее время он настроен на порт 5000 (http://localhost:5000/sportsstore/app.html). Ресурс Deployd работает на порту 5500 (http://localhost:5500/products). При нажатии на Deployd ответ будет следующим:

[
    { "name": "Kayak", "description": "A boat for one person", "category": "Watersports", "price": 275, "id": "a1c999fc248b2959" },
    { "name": "Lifejacket", "description": "Protective and fashionable", "category": "Watersports", "price": 48.95, "id": "61303717cfad182e" },
    { "name": "Soccer Ball", "description": "FIFA-approved size and weight", "category": "Soccer", "price": 19.5, "id": "0fb5f67bdcbd992f" },
    { "name": "Corner Flags", "description": "Give your playing field a professional touch", "category": "Soccer", "price": 34.95, "id": "24385d315dd388b4" },
    { "name": "Stadium", "description": "Flat-packed 35,000-seat stadium", "category": "Soccer", "price": 79500, "id": "500fb6805905a856" },
    { "name": "Thinking Cap", "description": "Improve your brain efficiency by 75%", "category": "Chess", "price": 16, "id": "637d8a1f42e6fa1c" },
    { "name": "Unsteady Chair", "description": "Secretly give your opponent a disadvantage", "category": "Chess", "price": 29.95, "id": "73393312ec7dfab7" },
    { "name": "Human Chess Board", "description": "A fun game for the family", "category": "Chess", "price": 75, "id": "7871d02a662b0915" },
    { "name": "Bling-Bling King", "description": "Gold plated, diamon-studded King", "category": "Chess", "price": 1200, "id": "b59a3389a0e248bd" }
]

Я пытаюсь получить эти данные с помощью $http.get:

$http.get("http://localhost:5500/products")
    .success(function (data) { ... })
    .error(function (error) { ... });

Тем не менее, это продолжает возвращать ошибку:

XMLHttpRequest cannot load http://localhost:5500/products. No 'Access-Control-Allow-Origin' header is present on the requested resource. Origin 'http://localhost:5000' is therefore not allowed access. 

Исследования показывают, что есть некоторые проблемы с Angular и CORS, и что заголовки должны быть настроены для выполнения междоменных запросов. В результате я добавил следующее в свой app.config:

$http.defaults.useXDomain = true;
delete $http.defaults.headers.common['X-Requested-With']; // this isn't needed anymore, but was put here as a just-in-case

Несмотря на добавление этих настроек, я все еще получаю сообщение об ошибке. В документации Deployd говорится, что он автоматически настроен для CORS ( Cross-Origin Requests) и отправит соответствующую информацию заголовка, если запрос не содержит недопустимых пользовательских заголовков. Я почти уверен, что мой запрос не содержит неверных пользовательских заголовков:

Accept: application/json, text/plain, */*
Cache-Control: max-age=0
Origin: http://localhost:5000
Referer: http://localhost:5000/sportsstore/app.html
User-Agent: Mozilla/5.0 (Windows NT 6.3; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/34.0.1847.131 Safari/537.36

Мой вопрос: есть ли какая-то другая конфигурация, которую мне нужно установить, чтобы настроить Deployd для обработки запроса CORS? В книге не указаны какие-либо специальные настройки угловых заголовков или что-либо еще.

7 ответов

Решение

Bic, обновите вашу версию deployd до версии 0.6.10. Это помогло мне. Теперь я был в состоянии обработать запрос на получение. Не похоже, что это ошибка с кодом AngularJS или книгой Адама Фримена.

В книге он упоминает, что он включает программу deployd с исходным кодом, загруженным по http://www.apress.com/9781430264484. Это версия 0.6.9. Я уверен, что с этим все в порядке. Это будет проще, чем пытаться найти версию 0.6.10, что я и сделал. Если вы хотите эту версию, вот она:

https://www.versioneye.com/nodejs/deployd/0.6.10

Это не установщик, поэтому вам нужно будет вставить его в каталог deployd, заменив node_modules,

Просто запустите "npm update" в папке установки deployd, и вы убедитесь, что вы обновились до последней версии 0.6.10. Это решило проблему для меня после прочтения ответов javaauthority (спасибо за это:)).

Вы можете поместить свои файлы (app.html, sportStore.js, ...) в общую папку вашего проекта Deployd и использовать следующий URLhttp://localhost:5500/app.html

Чтобы решить эту проблему, я запустил Chrome с флагом --disable-web-security. Но сначала зайдите в диспетчер задач и закройте все процессы Chrome, которые у вас есть.

Хотя я дал правильный ответ, а другие улучшили его, что, если вы не используете веб-сервер Deployd, упомянутый в книге? Я использую Wildfly (JBOSS 8.X), и мне пришлось заставить проблему CORS работать на нее. Я создал простой класс Java под названием CorsFilter. Импорт должен быть довольно легко найти, если вы используете Wildfly.

Надеюсь, что это помогает другим людям, которые имеют похожие проблемы с различными веб-серверами.

Обратите внимание: responseContext.getHeaders(). Add("Access-Control-Allow-Origin", "*");

Обратите внимание на * в строке выше? Это позволит ЛЮБЫМ запросам быть успешными. Обычно это хорошо для локальных разработок, но для сред производства / промежуточного уровня следует применять более строгие меры безопасности. Например, вы можете принять запрос только с определенного IP-адреса.

import org.jboss.resteasy.annotations.interception.HeaderDecoratorPrecedence;
import org.jboss.resteasy.annotations.interception.ServerInterceptor;

import javax.servlet.FilterChain;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.annotation.WebFilter;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.ws.rs.container.ContainerRequestContext;
import javax.ws.rs.container.ContainerResponseContext;
import javax.ws.rs.container.ContainerResponseFilter;
import javax.ws.rs.ext.Provider;
import java.io.IOException;

/**
 * Class to .
 * User: Java Authority
 * Date: 12/6/2014
 * Time: 12:38 PM
 */
@Provider
@ServerInterceptor
@HeaderDecoratorPrecedence
@WebFilter
public class CorsFilter implements ContainerResponseFilter {

    public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
        HttpServletRequest r = (HttpServletRequest)request;
        HttpServletResponse s = (HttpServletResponse)response;
        chain.doFilter(request, response);
    }


    @Override
    public void filter(ContainerRequestContext requestContext, ContainerResponseContext responseContext) throws IOException {
        responseContext.getHeaders().add("Access-Control-Allow-Origin", "*");
        responseContext.getHeaders().add("Access-Control-Allow-Headers", "Origin, X-Requested-With, Content-Type, Accept");
    }
}

Angular также отправляет пользовательские заголовки, которые отклоняет DPD, вставьте это в свой код для dev, чтобы удалить их, и DPD будет работать:

delete $http.defaults.headers.common['X-Requested-With'];

Я использовал Fiddler, чтобы изменить ответы от Deployd. Эта ссылка покажет, как добавить пользовательское правило в Fiddler, чтобы добавить Access-Control-Allow-Origin: * заголовок ко всем ответам. Работает отлично.

http://www.leggetter.co.uk/2010/03/19/using-fiddler-to-help-develop-cross-domain-capable-javascript-web-applications.html

Другие вопросы по тегам