I want to set the header Content-type: application/json in all my requests to my backend in Angular2. I use this in my main app.js file.
let headers = new Headers({
'Content-Type', 'application/json'
})
class MyOptions extends BaseRequestOptions {
headers: headers
}
bootstrap(App, [
provide(RequestOptions, {useClass: MyOptions}),
ROUTER_BINDINGS,
HTTP_PROVIDERS,
bind(APP_BASE_HREF).toValue('/')
])
I'm expecting all uses of Http to use the new content-type, but this code still has the content-type set to text/plain
saveMaster (master) {
return this.http
.put(`${config.API_URL}/masters/${master._id}`, JSON.stringify(master))
.map(res => res.json())
}
I have to manually set the headers for each request to get it work correctly. Am I doing something wrong?
Note: I want to set a header option globally, not have to set it with every request type like is found in this solution.
Change MyOptions to:
class MyOptions extends RequestOptions {
constructor() {
super({
method: RequestMethod.Get,
headers: new Headers({
'Content-Type': 'application/json',
'X-Some-Header': 'some-content'
});
});
}
}
Put provide(RequestOptions, {useClass: MyOptions}) AFTER HTTP_PROVIDERS (otherwise default BaseRequestOptions will be used instead of your MyOptions).
bootstrap(App, [
// ...
HTTP_PROVIDERS,
provide(RequestOptions, {useClass: MyOptions}) // <- after HTTP_PROVIDERS!!!
])
See this plunk
Related
In postman is a section where you can put or set a header. But how do i set it but in the navigator, that lasts over time through requests to different routes?
I´ve already tried setting a header, from the backend with differents methods like, and none of both worked:
res.header('x-token', jwt)
Or like
res.set('x-token', jwt)
And from the frontend i already tried with this methods and it didn´t work either:
const data = {id_token};
//let myHeaders = new Headers();
fetch(url, {
method: 'POST',
body: JSON.stringify(data),
headers:{
'Content-Type': 'application/json'
}
})
.then(resp => resp.json())
.then(({jwt}) => {
if (jwt) {
localStorage.setItem('x-token', jwt);
//None of both worked
//myHeaders.append('x-token', jwt);
//myHeaders.set('x-token', jwt);
}
})
.catch(error => console.error('Error:', error))
This is the header that i wanna send to the different routes:
https://i.stack.imgur.com/ueoxu.png
You can set the x-token header from your screen shot like this:
fetch(url, {
method: 'POST',
body: JSON.stringify(data),
headers:{
'Content-Type': 'application/json',
'x-token': 'eyJhbGciOiJIUzl.....'
}
}).then(...).catch(...)
Even though my code is inside one of my components in Vue, the problem is with Axios, let me explain why. So, I'm trying to get some information, like this:
axios.get('http://localhost:8181/roles/1',
{
headers: {
'Api-Token': 'tokenTOKEN',
'Content-Type': 'application/json'
}
}
)
.then(response => {console.log(response)})
.catch(response => {
console.log(response);
})
So, yes, I'm importing Axios correctly. Yes, I know we should not be sending a Content-Type header in a GET request. However, I already read the RFC 7231 and it doesn't say is impossible, is just not common. So, we want to send a Content-Type header in my request.
So, how do I know it doesn't work? Well, one of my middlewares in my Lumen API goes like this:
<?php
namespace App\Http\Middleware;
use Closure;
class JsonVerifier
{
public function handle($request, Closure $next)
{
if($request->isJson())
{
return $response = $next($request);
}
else
{
return response('Unauthorized.', 401);
}
}
}
I tried to use Postman to send that specific GET request, and it works. I tried to use fetch() like this:
var miInit = { method: 'GET',
headers: {
'Api-Token': 'tokenTOKEN',
'Content-Type': 'application/json'
},
mode: 'cors',
cache: 'default' };
fetch('http://localhost:8181/roles/1',miInit)
.then(function(response) {
console.log(response);
})
and it works! In both cases (with Postman and fetch()) my API returns the desire data.
However, when I try with Axios, I get a 401 response with the "Unauthorized" word, meaning that Axios didn't send the header correctly.
Now, the question. Is there any other way to send headers in an axios GET request? How can I force Axios to send the headers no matter what as it seem to be case with fetch() and Postman?
Axios automatically (as it should) removes the Content-Type header if you're sending a request without a body, as you do with any GET request.
https://github.com/axios/axios/blob/2ee3b482456cd2a09ccbd3a4b0c20f3d0c5a5644/lib/adapters/xhr.js#L112
// Add headers to the request
if ('setRequestHeader' in request) {
utils.forEach(requestHeaders, function setRequestHeader(val, key) {
if (typeof requestData === 'undefined' && key.toLowerCase() === 'content-type') {
// Remove Content-Type if data is undefined
delete requestHeaders[key];
} else {
// Otherwise add header to the request
request.setRequestHeader(key, val);
}
});
}
You're probably looking for the Accepts header and $request->wantsJson() (or acceptsJson()) instead.
I'm triggering a HTTP request and I'm getting a valid response from it. The response also has a header X-Token that I wish to read. I'm trying the below code to read the headers, however, I get null as a result
this.currentlyExecuting.request = this.http.request(reqParams.type, reqParams.url, {
body: reqParams.body,
responseType: 'json',
observe: 'response'
}).subscribe(
(_response: any) => {
// Also tried _response.headers.init();
const header = _response.headers.get('X-Token');
console.log(header);
onComplete(_response.body);
},
_error => {
onComplete({
code: -1,
message: Constants.WEBSERVICE_INTERNET_NOT_CONNNECTED
});
}
);
The response of the API, when checked in Chrome inspect, shows the header is present.
Have you exposed the X-Token from server side using access-control-expose-headers? because not all headers are allowed to be accessed from the client side, you need to expose them from the server side
Also in your frontend, you can use new HTTP module to get a full response using {observe: 'response'} like
http
.get<any>('url', {observe: 'response'})
.subscribe(resp => {
console.log(resp.headers.get('X-Token'));
});
In my case in the POST response I want to have the authorization header because I was having the JWT Token in it.
So what I read from this post is the header I we want should be added as an Expose Header from the back-end.
So what I did was added the Authorization header to my Exposed Header like this in my filter class.
response.addHeader("Access-Control-Expose-Headers", "Authorization");
response.addHeader("Access-Control-Allow-Headers", "Authorization, X-PINGOTHER, Origin, X-Requested-With, Content-Type, Accept, X-Custom-header");
response.addHeader(HEADER_STRING, TOKEN_PREFIX + token); // HEADER_STRING == Authorization
And at my Angular Side
In the Component.
this.authenticationService.login(this.f.email.value, this.f.password.value)
.pipe(first())
.subscribe(
(data: HttpResponse<any>) => {
console.log(data.headers.get('authorization'));
},
error => {
this.loading = false;
});
At my Service Side.
return this.http.post<any>(Constants.BASE_URL + 'login', {username: username, password: password},
{observe: 'response' as 'body'})
.pipe(map(user => {
return user;
}));
You should use the new HttpClient. You can find more information here.
http
.get<any>('url', {observe: 'response'})
.subscribe(resp => {
console.log(resp.headers.get('X-Token'));
});
As Hrishikesh Kale has explained we need to pass the Access-Control-Expose-Headers.
Here how we can do it in the WebAPI/MVC environment:
protected void Application_BeginRequest()
{
if (HttpContext.Current.Request.HttpMethod == "OPTIONS")
{
//These headers are handling the "pre-flight" OPTIONS call sent by the browser
HttpContext.Current.Response.AddHeader("Access-Control-Allow-Methods", "GET, POST, OPTIONS");
HttpContext.Current.Response.AddHeader("Access-Control-Allow-Headers", "*");
HttpContext.Current.Response.AddHeader("Access-Control-Allow-Credentials", "true");
HttpContext.Current.Response.AddHeader("Access-Control-Allow-Origin", "http://localhost:4200");
HttpContext.Current.Response.AddHeader("Access-Control-Expose-Headers", "TestHeaderToExpose");
HttpContext.Current.Response.End();
}
}
Another way is we can add code as below in the webApiconfig.cs file.
config.EnableCors(new EnableCorsAttribute("", headers: "", methods: "*",exposedHeaders: "TestHeaderToExpose") { SupportsCredentials = true });
**We can add custom headers in the web.config file as below. *
<httpProtocol>
<customHeaders>
<add name="Access-Control-Expose-Headers" value="TestHeaderToExpose" />
</customHeaders>
</httpProtocol>
we can create an attribute and decore the method with the attribute.
Happy Coding !!
You can get data from post response Headers in this way (Angular 6):
import { HttpClient, HttpHeaders, HttpResponse } from '#angular/common/http';
const httpOptions = {
headers: new HttpHeaders({ 'Content-Type': 'application/json' }),
observe: 'response' as 'response'
};
this.http.post(link,body,httpOptions).subscribe((res: HttpResponse<any>) => {
console.log(res.headers.get('token-key-name'));
})
You can get headers using below code
let main_headers = {}
this.http.post(url,
{email: this.username, password: this.password},
{'headers' : new HttpHeaders ({'Content-Type' : 'application/json'}), 'responseType': 'text', observe:'response'})
.subscribe(response => {
const keys = response.headers.keys();
let headers = keys.map(key => {
`${key}: ${response.headers.get(key)}`
main_headers[key] = response.headers.get(key)
}
);
});
later we can get the required header form the json object.
header_list['X-Token']
Angular 7
Service:
this.http.post(environment.urlRest + '/my-operation',body, { headers: headers, observe: 'response'});
Component:
this.myService.myfunction().subscribe(
(res: HttpResponse) => {
console.log(res.headers.get('x-token'));
} ,
error =>{
})
Try this simple code.
1. Components side code: to get both body and header property. Here there's a token in body and Authorization in the header.
loginUser() {
this.userService.loginTest(this.loginCred).
subscribe(res => {
let output1 = res;
console.log(output1.body.token);
console.log(output1.headers.get('Authorization'));
})
}
2. Service side code: sending login data in the body and observe the response in Observable any which be subscribed in the component side.
loginTest(loginCred: LoginParams): Observable<any> {
const header1= {'Content-Type':'application/json',};
const body = JSON.stringify(loginCred);
return this.http.post<any>(this.baseURL+'signin',body,{
headers: header1,
observe: 'response',
responseType: 'json'
});
}
I had to do the following to get the headers to appear in SPA Angular application when GETting them from ASP.NET Core service:
var builder = WebApplication.CreateBuilder(args);
services.AddCors(options =>
{
options.AddPolicy("MyExposeResponseHeadersPolicy",
builder =>
{
builder.WithOrigins("https://*.example.com")
.WithExposedHeaders("x-custom-header");
});
});
builder.Services.AddControllers();
var app = builder.Build();
I was trying to make an API call to another domain, which has no-cors enabled.
The API call was made something like this:
let url = `https:sampleApiUrl?params=xxxx`;
console.log("hitting dashboard url")
get(url, token)
.then((resp) => {
console.log("resp", resp)
})
.catch((error) => {
console.log(error)
})
This API call, subsequently calls a 'get' method:
const get = (url, authToken) => {
return baseFetch(url, 'get', false, authToken).then(response => {
if (response.status >= 200 && response.status < 300) {
return response.json();
} else {
const error = new Error(response.statusText);
error.response = response;
throw error;
}
});
}
Now, this get method calls a baseFetch method:
const baseFetch = (url, verb, body, authToken) => {
const request = {
method: verb,
headers: {
'Accept': 'application/json',
'Content-Type': 'application/json',
'X-Requested-With': 'XMLHttpRequest',
'Access-Control-Allow-Origin': '*',
'credentials': 'include'
},
mode: 'cors'
}
if (authToken){
// adding x-access-token in the request header
request.headers['x-access-token'] = authToken;
}
if (body){
request.body = JSON.stringify(body);
}
return fetch(url, request);
}
Now, when this API call is requested, I can't see the "x-access-token" populated in the browser network call.
No x-access-token in request-headers
Also, I am not sure why I get status code 204 in response.
Calling this API from postman and directly from browser or calling as a curl request, returns the correct response.
Thanks
Looking at the image, you are looking at the headers for pre flight OPTIONS method and not the GET method. The pre flght request is generated by the browser and it never has any custom header. therefore it did not have the x-access-token in its headers.
Trying to send a post request to my Laravel API from the angular 2 app.
My method:
getCombinas(test)
{
this.loadedResult = false;
let body = JSON.stringify({
test: test,
});
this.http.request('testAPI', { body:body, method:'POST' })
.map((res:Response) => res.json())
.subscribe(
data => {
console.log(data);
},
error => {
console.log(error.text());
}
);
}
In my httpd.conf (apache configuration) I allowed cors:
Header set Access-Control-Allow-Origin "*"
And I'm using custom request options class in my angular 2 app:
import {BaseRequestOptions, RequestOptions, RequestOptionsArgs, Headers} from '#angular/http';
export class CustomRequestOptions extends BaseRequestOptions {
merge(options?:RequestOptionsArgs):RequestOptions {
options.url = 'MY_API_URL/api/' + options.url;
if (options.method === 1) {
let headers = new Headers();
headers['Content-Type'] = 'application/json';
headers.append('Content-Type', 'application/json');
options.headers = headers;
}
return super.merge(options);
}
}
The error occured only after I added those 2 lines:
headers['Content-Type'] = 'application/json';
headers.append('Content-Type', 'application/json');
But without them, My Laravel get text/plain response and I can't use it.. I need JSON response.
What's wrong?
If missing you have to enable apache mod_header with command
a2enmod headers
then restart apache
It looks like you should additionally write Access-Control-Allow-Headers header with necessary value to response.