简体   繁体   English

在Angular 2 http.post上添加任何选项或标题会发送OPTIONS

[英]Adding any options or headers on the Angular 2 http.post sends OPTIONS

I am trying to send token information back to the server over http.post() . 我正在尝试通过http.post()将令牌信息发送回服务器。 If I remove the options from it it sends a POST but if I add them back on it sends OPTIONS which is rejected from the server code. 如果我从中删除选项,它将发送POST,但如果将其重新添加,则会发送从服务器代码中拒绝的OPTIONS。 I tried removing the "withCredentials" as well. 我也尝试删除“ withCredentials”。

export class EntityService {

    public entity: EntityModel;
    private options: RequestOptions;

    constructor( @Inject(Http) private http: Http, @Inject(AuthenticationService) authService) {
        let headers = new Headers({ 'X-Authorization': 'Bearer ' + authService.token});
        this.options = new RequestOptions({ headers: headers, withCredentials: true });
    }

    public store(entity: EntityModel): Observable<string> {

        var request;
        if (!entity.uuid) {
            request = this.http.post("http://localhost:8080/api/entity", JSON.stringify(entity), this.options);
        }
        else {
            request = this.http.put("http://localhost:8080/api/entity", JSON.stringify(fact), this.options);
        }
        return request.map((res: Response) => res.text());
    }
}

My authentication service looks like this: 我的身份验证服务如下所示:

import { Injectable, Inject } from '@angular/core';
import { Http, Headers, Response } from '@angular/http';
import { Observable } from 'rxjs';
import 'rxjs/add/operator/map'

//http://jasonwatmore.com/post/2016/08/16/angular-2-jwt-authentication-example-tutorial
@Injectable()
export class AuthenticationService {
    public token: string;

    constructor(@Inject(Http) private http: Http) {
        // set token if saved in local storage
        var currentUser = JSON.parse(localStorage.getItem('currentUser'));
        this.token = currentUser && currentUser.token;
    }

    login(username: string, password: string): Observable<boolean> {;
        console.log("login...");
        return this.http.post('http://localhost:8080/api/auth/login', JSON.stringify({ username: username, password: password }))
            .map((response: Response) => {
                // login successful if there's a jwt token in the response
                let token = response.json() && response.json().token;
                if (token) {
                    // set token property
                    this.token = token;

                    // store username and jwt token in local storage to keep user logged in between page refreshes
                    localStorage.setItem('currentUser', JSON.stringify({ username: username, token: token }));

                    // return true to indicate successful login
                    return true;
                } else {
                    // return false to indicate failed login
                    return false;
                }
            });
    }

    logout(): void {
        // clear token remove user from local storage to log user out
        this.token = null;
        localStorage.removeItem('currentUser');
    }
}

Here is my Spring configuration: 这是我的Spring配置:

@SpringBootApplication
public class SpringBootApp extends WebMvcConfigurerAdapter {

    private boolean workOffline = true;
    private boolean setupSchema = false;
    private IGraphService graphService;
    private DbC conf;

    @Autowired
    public SpringBootApp(IGraphService graphService, DbC conf)
    {
        this.graphService = graphService;
        this.conf = conf;
    }

    public static void main(String[] args) throws Exception {
        SpringApplication.run(SpringBootApp.class, args);
    }

    @Bean
    public Filter caseInsensitiveRequestFilter() {
        return new CaseInsensitiveRequestFilter();
    }

    @Override
    public void configureDefaultServletHandling(DefaultServletHandlerConfigurer configurer) {
        configurer.enable();
    }

    @Override
    public void addCorsMappings(CorsRegistry registry) {
        registry.addMapping("/**")
                .allowedOrigins("http://localhost:3000")
                .allowedMethods("GET", "PUT", "POST", "DELETE","OPTIONS");
    }

    @Bean
    public FilterRegistrationBean corsFilter() {
        UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
        CorsConfiguration config = new CorsConfiguration();
        config.setAllowCredentials(true);
        config.addAllowedOrigin("http://localhost:3000");
        config.addAllowedHeader("*");
        config.addAllowedMethod("*");
        source.registerCorsConfiguration("/**", config);
        FilterRegistrationBean bean = new FilterRegistrationBean(new CorsFilter(source));
        bean.setOrder(0);
        return bean;
    }
}

I really don't know what to do since I am following what is being said in Angular2 OPTIONS method sent when asking for http.GET and this is not a preflight request. 我真的不知道该怎么办,因为我正在跟踪在请求http.GET时发送的Angular2 OPTIONS方法中所说的内容 ,这不是预检请求。 I had this issue earlier with the wrong content-type. 之前我曾因内容类型错误而遇到此问题。

The OPTIONS request is made by the browser alone. OPTIONS请求仅由浏览器发出。 Angular is not involved at all. Angular根本不涉及。

"and this is not a preflight request." “而且这不是飞行前的要求。” - it definitely is. -当然是。

You need to configure your server to respond properly to the OPTIONS request or ensure that the Angular application is loaded from the same server (also same port) as where you make the request to. 您需要配置服务器以正确响应OPTIONS请求,或确保从与请求相同的服务器(也是同一端口)加载Angular应用程序。

The actual fix was due to two reasons: improper CORS implementation - for more please have a look here: Spring 4/5 global CORS configuration doesn't work giving `No 'Access-Control-Allow-Origin' header is present on the requested resource` 实际的修复有两个原因:不正确的CORS实施-请在此处查看更多信息: Spring 4/5全局CORS配置无法正常工作,因为在请求的请求中没有'Access-Control-Allow-Origin'标头资源`

Then when I was POSTing after the login I was getting error 415 Unsupported Media Type . 然后,当我在登录后进行发布时,出现错误415 Unsupported Media Type After following the instructions here: POST JSON fails with 415 Unsupported media type, Spring 3 mvc 按照此处的说明进行操作后: POST JSON失败,显示415不支持的媒体类型,Spring 3 mvc

I added Content-Type and Accept header on my request and it fixed the problem. 我在请求中添加了Content-TypeAccept标头,它解决了该问题。 It seems that Content-Type is what was actually needed. 似乎Content-Type是实际需要的。

export class EntityService {

    public entity: EntityModel;
    private options: RequestOptions;

    constructor( @Inject(Http) private http: Http, @Inject(AuthenticationService) authService) {
        let headers = new Headers({ 
           'X-Authorization': 'Bearer ' + authService.token,
           'Content-Type': 'application/json'
        });
        this.options = new RequestOptions({ headers: headers, withCredentials: true });
    }

    public store(entity: EntityModel): Observable<string> {

        var request;
        if (!entity.uuid) {
            request = this.http.post("http://localhost:8080/api/entity", JSON.stringify(entity), this.options);
        }
        else {
            request = this.http.put("http://localhost:8080/api/entity", JSON.stringify(fact), this.options);
        }
        return request.map((res: Response) => res.text());
    }
}

Using http post like this 像这样使用http发布

import { Http, Headers, Response, Request } from '@angular/http';

let headers = new Headers();
headers.append('Content-Type', 'application/json');
headers.append('X-Authorization', this.token);
headers.append('Authorization', 'Bearer ' + jwtToken);

return this.http.post(url, data, {headers})
  .map(res => { console.log(res) })
  .catch(err => { console.log(err) } );

Note this example returns an Observable that you can subscribe to. 请注意,此示例返回您可以订阅的Observable。 Also my example 也是我的例子

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM