Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Angular HttpClient doesn't send POST, it sends OPTIONS

Im' newbie using Angular HttpClient (and writting english too)

I have a problem, I'm trying sending HTTP request with POST method in order to negociate OAuth token obtenction but angular sends OPTIONS request:

Service:

login(username: string, password: string) {
const body = `username=${encodeURIComponent(username)}&password=${encodeURIComponent(password)}&grant_type=password`;

const httpOptions = {
  headers: new HttpHeaders({
    'Content-Type': 'application/x-www-form-urlencoded',
    'Authorization': 'Basic ' + btoa(TOKEN_AUTH_USERNAME + ':' + TOKEN_AUTH_PASSWORD)
  })
};  


return this.http.post<string>(AuthenticationService.AUTH_TOKEN, body, httpOptions);

Result:

enter image description here

For my backend, I'm using Spring Security and i added a filter to allow CORS:

@Bean
public FilterRegistrationBean corsFilter() {
    UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
    CorsConfiguration config = new CorsConfiguration();
    config.setAllowCredentials(true);
    config.addAllowedOrigin("*");
    config.addAllowedHeader("*");
    config.addAllowedMethod("*");
    source.registerCorsConfiguration("/**", config);
    FilterRegistrationBean bean = new FilterRegistrationBean(new CorsFilter(source));
    bean.setOrder(0);
    return bean;
}
like image 740
Jose A. Matarán Avatar asked Feb 27 '18 14:02

Jose A. Matarán


People also ask

What does HttpClient post return Angular?

The HttpClient. post() returns Observable instance of given response type. On this page we will see injecting HttpClient , creating request body and passing HTTP options. We will also look into error handling. For the demo we will use Angular In-Memory Web API to post data.

Can Angular handle post request?

It is a bit awkward requirement since Angular is JavaScript framework and It does not accept post request because post request needs to be handled at server side only not at client side.

What is the type returned by an HttpClient get () method?

Use the HttpClient.get() method to fetch data from a server. The asynchronous method sends an HTTP request, and returns an Observable that emits the requested data when the response is received. The return type varies based on the observe and responseType values that you pass to the call.

How do you perform error handling for HttpClient in Angular?

The basic way to handle errors in Angular is to use Angular's HttpClient service along with RxJS operators throwError and catchError. The HTTP request is made, and it returns the data with a response if anything wrong happens then it returns an error object with an error status code.


2 Answers

The OPTIONS request is sent first because of CORS, Angular needs permission from your backend in order to know if it can POST. So on your backend you need to enable CORS in order for the http request to go.

like image 189
Mike Tung Avatar answered Oct 04 '22 01:10

Mike Tung


It is not angular related, it is your browser doing.

Check this issue.

I assume your server runs at localhost:8080, and your angular application at localhost:4200. Since, your request is a cross origin request, browser first sends an OPTIONS request to see if it is safe. At this point, your server returns a response with http code 401 which prevents the post request from being made. Either you have to do some config in your server or you can use webpack proxy. This is just for your local machine. If you serve your bundled angular application from your server, then you won’t have to do anything for production. I’ve been using this technique for quite some time, and it works just fine.

Example,

Users access my angular application from mydomain.com/ng-app I also serve my rest api from same domain, mydomain.com/api

So my application always make the request to the server it’s being served from which causes no problem in production.

For latter, you can do following

Create a proxy.conf.json at the root of your project (next to package.json) And put following inside

{
    "/api/": {
        "target": "http://localhost:8080",
        "secure": false,
        "changeOrigin": true
    }
}

In package.json, edit your start script and make it ng serve --proxy-config proxy.conf.json

Also, from your frontend, do not send the requests to localhost:8080 directly, instead just write something like http.post('/api/getSomeData') which will make the request to localhost:4200 which will redirect it to localhost:8080. This way, you won't have to deal with CORS.

like image 24
Bunyamin Coskuner Avatar answered Oct 04 '22 02:10

Bunyamin Coskuner