not allowed by Access-Control-Allow-Headers when using JSON headers - apache

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.

Related

How to pass authorization token in header for GET method using XMLHttpRequest in react native

I am new to react-native. I am trying to pass the authorization token through a header in the GET method. But I am getting an unauthorized error.
I have already tried this code "Using an authorization header with Fetch in React Native" not working for me and also with XMLHttpRequest()
But the API works fine in postman, Java(core) and Android.
Do we have any special implementation in react-native to pass headers?
Could anyone can help me with this?
My code: Changed the server name.
getData() {
var data = null;
var xhr = new XMLHttpRequest();
xhr.withCredentials = true;
xhr.addEventListener("readystatechange", function () {
if (this.readyState === 4) {
console.log(this.responseText);
}
});
xhr.open("GET", "https://xyz-test-server.server.com/api/v3/users/details/");
xhr.setRequestHeader("Authorization", "Basic cC5qYWltdXJ1Z2FuLm1jYUBnbWFpbC5jb206MTIzNDU2");
xhr.setRequestHeader("User-Agent", "PostmanRuntime/7.17.1");
xhr.setRequestHeader( "Content-Type", "application/x-www-form-urlencoded; charset=ISO-8859-1");
xhr.setRequestHeader("Accept", "*/*");
xhr.setRequestHeader("Cache-Control", "no-cache");
xhr.setRequestHeader("Postman-Token", "d8ae56bf-1926-44e4-9e94-23223234,93a110a2-ee8e-42d5-9f7b-45645ddsfg45");
xhr.setRequestHeader("Accept-Encoding", "gzip, deflate");
xhr.setRequestHeader("Connection", "keep-alive");
xhr.setRequestHeader("cache-control", "no-cache");
xhr.send(data);
}
Fetch method:
async _getProtectedQuote() {
fetch('https://xyz-test-server.server.com/api/v3/users/details/', {
method: 'GET',
headers: new Headers({
'Authorization': 'Basic cC5qYWltdXJ1Z2FuLm1jYUBnbWFpbC5jb206MTIzNDU2',
'Content-Type': 'application/x-www-form-urlencoded'
}),
}).then(responseJson => {
alert(JSON.stringify(responseJson));
console.log(responseJson);
});
}
You can try interceptor for pass token into header.
Put all requests in one service file name service.js then import Interceptor from '../interceptor';
make one interceptor.js file and write below code in file.
import axios from 'axios';
axios.interceptors.request.use(async (config) => {
if (config.method !== 'OPTIONS') {
config.headers.Authorization = 'Basic cC5qYWltdXJ1Z2FuLm1jYUBnbWFpbC5jb206MTIzNDU2';
}
return config;
}, function (error) {
// Do something with request error
console.log('how are you error: ', error);
return promise.reject(error);
});
axios.interceptors.response.use(
(response) => {
return response
},
async (error) => {
// const originalRequest = error.config
console.log("error in interceptors=============>", error);
if (error.response.status === 500) {
alert(error.response.data.message);
NavigationService.navigate('Login');
} else {
return Promise.reject(error)
}
}
)
export default axios;
When api calls header will pass through by interceptor automatically.
Fetch Api converts all headers into lower-case. We need to do case-insensitive server side parsing.

Capture a Response from GET and Use it in the Next Request

I am trying to use the response of axios.get, and use it in axios.post. How can I use the response as a header in the POST request?
I tried using axios.post with headers defined in the request config:
var config = {
headers: {
'Access-Control-Allow-Origin': '*',
'user': newUser.eid,
'pass':'bd957c3fbb'
}
}
/*
const axios = require('axios')
getCrumb() {
return axios.get('https://jenkins.com/crumbIssuer/api/xml?xpath=concat(//crumbRequestField,":",//crumb)', config)
.then(response => {
return response
})
}
*/
/* code to get jenkins crumb */
const getJenkinsCrumb = () => {
try {
return axios.get('https://jenkins.com/crumbIssuer/api/xml?xpath=concat(//crumbRequestField,":",//crumb)', config)
.then((crumbValue) => {
console.log(crumbValue.data);
})
} catch (error) {
console.log(error)
}
}
getJenkinsCrumb();
I want use the response from the previous GET request (above) as a header in the POST call (below).
var crumbHeader = {
headers: {
'Access-Control-Allow-Origin': '*',
}
}
/* post api to kick off the build */
try {
return axios.post('https://abc123:bd95701859#jenkins.com/job/Non- PAR/job/Non-Prod-Jobs/job/uitest/job/TestJob/buildWithParameters?nodes=100000&clustername=clustername', crumbHeader)
.then((postKickTest) =>{
console.log(postKickTest.data);
})
} catch (error) {
console.log(error)
}
The Axios request config includes a headers property to specify the request's headers. The config can be specified as the 2nd argument of axios.post() (if using the two-argument signature) or the 3rd argument (if using the three-argument signature). This example demonstrates the two-argument signature of axios.post() that sets the headers with the dataresult of a previous request:
export default {
methods: {
async sendRequest() {
const userResp = await axios.get('https://reqres.in/api/users/2')
await axios.post('https://reqres.in/api/users', {
headers: userResp.data,
data: {
name: 'john doe',
job: 'leader',
}
})
},
}
}
demo
Side note: The Access-Control-Allow-Origin is a CORS header that can only be set by the server. It has no effect when sent from the client. It's possible you're incorrectly assuming that header is not reaching the server because it's not resolving a CORS issue.

Put Http request return 401 error in Ionic

I am trying to do put request to the server ,but I am getting 401 error
The provider
putData(){
header = header.append('Content-Type', 'application/json');
header = header.append('Accept', 'application/json');
header = header.append('Authorization', 'Bearer');
return this.http.put('http://something//', {headers: header})
.subscribe((result: any) => {
console.log(result);
}, (errorResponse) => {
console.error(errorResponse);
}
home.ts
this.MyProvider.putData();
I have attach the network header as well since the first request success, but the second does not ?!!!
import { HttpClient, HttpParams, HttpHeaders} from '#angular/common/http';
constructor(public http: HttpClient )
putData(){
const headers = new HttpHeaders({'Authorization':'Basic'});
return this.http.post("'http://something//'", {headers: headers});
}
i think you code header is not adding properly try this method to add header

How to get the headers from HTTP response when using http.post [duplicate]

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();

How do you set global custom headers in Angular2?

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