$http.get doesn't have all headers - javascript

I'm trying to download a file from my web-api controller. I succeded until I wanted to get the custom header of the response.
web-api controller
[HttpGet]
[Route("vorlage")]
[ResponseType(typeof(object))]
[SwaggerResponse(HttpStatusCode.OK, Type = typeof(object))]
public HttpResponseMessage DownloadVorlage()
{
HttpResponseMessage result = Request.CreateResponse(HttpStatusCode.OK);
result.Content = new ByteArrayContent(Properties.Resources.Vorlage_Batch);
result.Content.Headers.ContentDisposition = new ContentDispositionHeaderValue("attachment");
result.Content.Headers.ContentDisposition.FileName = "original name.xlsx";
result.Content.Headers.ContentType = new MediaTypeHeaderValue("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet");
result.Headers.Add("X-Filename", "original name.xlsx");
return result;
}
angularjs code
function DownloadVorlage($scope, $http, WebApiBaseUri) {
var request = {
method: 'GET',
url: WebApiBaseUri + 'batchmode/vorlage',
responseType: 'arraybuffer',
headers: {
'Accept': 'application/json;odata=verbose'
}
};
$http(request).then(function (response) {
var headers = response.headers();
var filename = headers['X-Filename'] || 'replacement name.xlsx';
var contentType = headers['content-type'] || 'application/octet-stream';
download(response.data, filename, contentType);
}, function (response) {
console.log(response);
});
}
The content is in the right type and it is possible to save the file.
When I test the API with postman I got all headerinformation that I need.
But all header information I go are:
cache-control: "no-cache"
content-type: "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet"
expires: "-1"
pragma: "no-cache"
I'm missing the "X-Filename" information and have no clue how to get it.

Related

Azure http-trigger function to query HTTP POST request with multipart/form-data

I am using Azure function apps with C# (or NodeJS). How to write a http post request to achieve below task?
Http triger function app should send an HTTP request to a different server to get some data.
Read the incoming response and send back by the http trigger source as a JSON file.
I am new to Azure function and your support would be greatly helpful.
For example
URL: https://postman-echo.com/post
HTTP's headers:
Accept: */*
Accept-Encoding: gzip, deflate, br
Connection: Keep-Alive
Content-Length: 1330
Content-Type: multipart/form-data;boundary=XXXXabcXXXX
Keep-Alive: timeout=30000
Transfer-Encoding: chunked
HTTP Body:
--XXXXabcXXXX
Content-Disposition: form-data; name="RequestData"
Content-Type: application/JSON; charset=utf-8
Content-Transfer-Encoding: 8bit
{
"cmdDict":
{
"application":"b",
"application_session_id":"cd"
},
"appId": "123",
"uId":"345645"
}
--XXXXabcXXXX
Content-Disposition : form-data; name="Parameter"; paramName="REQUEST_INFO"
Content-Type: application/json; charset=utf-8
Content-Transfer-Encoding: 8bit
{
"abc":
{"x":"default",
"y":[],
"message":"HELLO WORLD"
},
"D":1
}
--XXXXabcXXXX--
Here's how you can do the multipart/form-data request with Node.js in Azure Functions.
The only dependency you need to install is form-data from npm.
const https = require('https')
const FormData = require('form-data')
const host = 'postman-echo.com'
const path = '/post'
const method = 'POST'
const requestHeaders = {
Accept: '*/*',
// add headers here as necessary
}
const parts = [
{
name: 'RequestData',
data: {
cmdDict: {
application: 'b',
application_session_id: 'cd',
},
appId: '123',
uId: '345645',
},
contentType: 'application/json; charset=utf-8',
},
{
name: 'Parameter',
data: {
abc: { x: 'default', y: [], message: 'HELLO WORLD' },
D: 1,
},
contentType: 'application/json; charset=utf-8',
},
]
async function fetchFromOrigin() {
return new Promise((resolve, reject) => {
const form = new FormData()
parts.forEach((part) =>
form.append(part.name, JSON.stringify(part.data), {
contentType: part.contentType,
}),
)
const options = {
host,
path,
method,
headers: Object.assign({}, requestHeaders, form.getHeaders()),
}
const req = https.request(options, (res) => {
if (res.statusCode < 200 || res.statusCode > 299) {
return reject(new Error(`HTTP status code ${res.statusCode}`))
}
const body = []
res.on('data', (chunk) => body.push(chunk))
res.on('end', () => {
const resString = Buffer.concat(body).toString()
resolve(resString)
})
})
req.on('error', (err) => reject(new Error(err.message)))
form.pipe(req)
})
}
module.exports = async function (context, req) {
const res = await fetchFromOrigin()
context.res = {
body: res,
}
}
Please refer to this code:
using System.Threading.Tasks;
using Microsoft.AspNetCore.Mvc;
using Microsoft.Azure.WebJobs;
using Microsoft.Azure.WebJobs.Extensions.Http;
using Microsoft.AspNetCore.Http;
using Microsoft.Extensions.Logging;
using Newtonsoft.Json;
using System.Net.Http;
using System.Net.Http.Headers;
using System;
namespace FunctionMultipart
{
public static class Function1
{
[FunctionName("Function1")]
public static async Task<IActionResult> Run(
[HttpTrigger(AuthorizationLevel.Anonymous, "get", "post", Route = null)] HttpRequest req,
ILogger log)
{
log.LogInformation("C# HTTP trigger function processed a request.");
HttpClient _httpClient = new HttpClient();
string URL = "https://postman-echo.com/post";
using (var multiPartStream = new MultipartFormDataContent("XXXXabcXXXX"))
{
StringContent jsonPart1 = new StringContent("{\"cmdDict\": {\"application\":\"b\",\"application_session_id\":\"cd\"},\"appId\": \"123\",\"uId\":\"345645\"}");
jsonPart1.Headers.ContentDisposition = new ContentDispositionHeaderValue("form-data");
jsonPart1.Headers.ContentType = new MediaTypeHeaderValue("application/json");
StringContent jsonPart2 = new StringContent("{\"abc\":{\"x\":\"default\",\"y\":[],\"message\":\"HELLO WORLD\"},\"D\":1}");
jsonPart2.Headers.ContentDisposition = new ContentDispositionHeaderValue("form-data");
jsonPart2.Headers.ContentType = new MediaTypeHeaderValue("application/json");
multiPartStream.Add(jsonPart1, "RequestData");
multiPartStream.Add(jsonPart2, "Parameter");
HttpRequestMessage request = new HttpRequestMessage(HttpMethod.Post, URL);
request.Content = multiPartStream;
//"application/json" - content type
request.Headers.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
request.Headers.AcceptEncoding.Add(new StringWithQualityHeaderValue("gzip"));
request.Headers.AcceptEncoding.Add(new StringWithQualityHeaderValue("deflate"));
request.Headers.AcceptEncoding.Add(new StringWithQualityHeaderValue("br"));
request.Headers.Connection.Add("Keep-Alive");
//request.Headers.Add("Content-Length", "1330");
//request.Headers.Add("Content-Type", "multipart/form-data;boundary=XXXXabcXXXX");
HttpCompletionOption option = HttpCompletionOption.ResponseContentRead;
System.Net.ServicePointManager.ServerCertificateValidationCallback = ((sender, certificate, chain, sslPolicyErrors) => true);
using (HttpResponseMessage response = _httpClient.SendAsync(request, option).Result)
{
if (response.IsSuccessStatusCode)
{
String result = response.Content.ReadAsStringAsync().Result;
//var deserializedObject = JsonConvert.DeserializeObject<T>(response.Content.ReadAsStringAsync().Result);
//return deserializedObject.ToString();
log.LogInformation(result);
}
}
}
return new OkObjectResult("ok");
}
}
}

x-www-form-urlencoded post parameters (body) in frisby npm not working

I'm trying to test rest endpoint 'http://xxxxxxx/j_spring_security_check' to get authentication with frisby npm package.
I am able to work in postman, by selecting request body as 'x-www-form-urlencoded' tab and given my app credentials like key-value, its working fine as expected. But in frisby npm I am unable to set request body as 'x-www-form-urlencoded'.
I'm unable to login with this script.
Please help me in this or any other alternative suggestions would be great.
Here is my code:
var frisby7=require('frisby');
const qs = require('qs');
describe('API reference', function() {
var baseURL='http://xxxxxx/j_spring_security_check';
it('Simple Test with post url-encode form body request ', function() {
console.log("**********")
frisby7.globalSetup({
request: {
headers:{'Content-Type':'application/x-www-form-urlencoded'}
// headers: { 'X-Ms-Source':'api','X-Ms-Format':'xml','Authorization':'Basic c2hyZXlhIGdveWFsOm0jbWY4cDlMZ2ZAMU1xUTg='}
}
});
return frisby7.post(baseURL,
{
form: { j_username:'xxxx#xxxxx.com', j_password:'xxxx' }
}).then(function (res) { // res = FrisbyResponse object
console.log('status '+res.status);
console.log('body '+res.body);
//return res;
});
});
You are currently sending the object in the body as if you were using 'multipart/form-data'.
To send the request as 'application/x-www-form-urlencoded' you need to URI encode each property and then post them as a querystring
Try it like this
var objToSend = { j_username:'xxxx#xxxxx.com', j_password:'xxxx' };
var uriObj = Object.keys(objToSend).map(key => encodeURIComponent(key) + '=' + encodeURIComponent(objToSend[key])).join('&');
var url = baseURL + '?' + uriObj
frisby7.post(url);
Try something like this:
var frisby = require("frisby");
const Joi = frisby.Joi;
var req1 = {
method: "get",
url: "pass url here",
headers : {
"Accept": "application/json",
"content-type" : "application/json",
'Authorization': 'Basic ' + Buffer.from(username + ":" + password).toString('base64') // pass username and password for //validation
},
body: {}
};
describe('spec file name', function () {
it("spec file name" + dateTime, function(){
return frisby
.setup({ request: { headers : req1.headers } })
.get(req1.url)
.expect("status", 200)
.expect("header", "Content-Type", "application/json; charset=utf-8")
.expect("jsonTypes", {
"message": Joi.string()
})
.then(function(res) {
var body = res.body;
body = JSON.parse(body);
expect(body.message).toBeDefined();
})
.then(function(res) {
var body = res.body;
body = JSON.parse(body);
var req2 = {
method: "put",
url: "pass url here",
headers : {
"Accept": "application/json",
"content-type" : "application/json",
"Authorization": "JWT " + Token // anything that you using to authenticate
},
body: {}
};
return frisby
.setup({ request: { headers : req2.headers } })
.put(req2.url)
.expect("status", 200)
.expect("header", "content-type", "application/json; charset=utf-8")
.expect("jsonTypes", {
"message": Joi.string()
})
.then(function(res) {
var body = res.body;
body = JSON.parse(body);
expect(body.message).toBeDefined();
})
});
});
});

Why are the request headers in the following Angular 5 code not been passed in the request?

So I can't get this http request object to send my headers along with request.
loginUser(email,password){
console.log("loginuser");
let formData:FormData = new FormData();
formData.append("format","json");
formData.append("email",email);
formData.append("password",password);
let headers = new HttpHeaders();
headers.append('command', 'ProcessLoginPos');
headers.append('Access-Control-Allow-Origin', '*');
const req = new HttpRequest('POST', 'http://localhost:8080/ProjectOne/', formData, { 'headers':headers, reportProgress: true, responseType: 'text' });
return this.http.request(req,{},{"command": "ProcessLoginPos"});
}
Your last line should follow this pattern:
return this.http.post(url, body, { headers: headers, params: params })
And finally you should get something like:
return this.http.post('http://localhost:8080/ProjectOne/', formData, { headers: headers })
Result (but I have no idea, why do you need new FormData() here):
loginUser(email, password) {
let formData: FormData = new FormData();
formData.append("format", "json");
formData.append("email", email);
formData.append("password", password);
let headers = new HttpHeaders();
headers.append('command', 'ProcessLoginPos');
headers.append('Access-Control-Allow-Origin', '*');
return this.http.post('http://localhost:8080/ProjectOne/', formData, { headers: headers })
}

HTTP headers not getting sent with fetch()

I'm trying to configure the backend API on my app and here's the code to send a request:
static async xhr(endpoint, args, method) {
const url = `${API_SERVER}${endpoint}`;
let formBody = [];
for (let property in args) {
let encodedKey = encodeURIComponent(property);
let encodedValue = encodeURIComponent(args[property]);
formBody.push(encodedKey + "=" + encodedValue);
}
formBody = formBody.join("&");
let options = Object.assign({ method: method }, args ? { body: formBody } : null );
try {
let headers = {
'Accept': 'application/json',
'Content-Type': 'application/x-www-form-urlencoded',
};
accessToken = 'bdi8HD8js91jdoach7234h';
if(accessToken != null)
headers['Authorization'] = accessToken;
options.headers = headers;
return fetch(url, options).then( resp => {
console.log(resp);
let json = resp.json();
if(resp.status >= 200 && resp.status < 300) {
if (resp.ok) {
return json
}
} else {
return {};
}
return json.then(err => {throw err});
});
} catch (error) {
return null;
}
}
Note: I debugged and found that the headers are correctly getting added to the options variable, but for some reason, the server isn't receiving the Authorization header.
I used Postman to send the exact same request with the exact same headers and I'm getting the correct response via it. I have no idea what's wrong, except it would only be so if the headers aren't getting sent in the first place.
Can someone please tell me what am I doing wrong? Thanks!
The headers option has to be an instance of Headers. You can transform your current headers object to a Headers instance by passing it to its constructor like this:
const headers = new Headers({
'Accept': 'application/json',
'Content-Type': 'application/x-www-form-urlencoded',
});
Note that I also replaced let with const since that variable is not going to be reassigned.
To change a header or add a new header to that Headers instance, you can use the set method. Instead of headers['Authorization'] = accessToken you'd do ...
headers.set('Authorization', accessToken)

Grails upload files with angular

i have an angular ui and grails as end points, i posted the files it went ok, but grails seems can't read it.
my angular codes
function sendComment(comment, cb, cbError,token) {
//var promise = $q.defer();
var formData = new FormData();
formData.append('email', comment.email);
formData.append('PNR', comment.PNR);
formData.append('content', comment.content);
formData.append('commentFile',file);
var req = {
method: 'POST',
url: ENV.baseurl +"api/addComment",
transformRequest: angular.identity,
headers: {
'Accept': "application/json",
'Content-Type': undefined,
'Authorization': 'Bearer '+token,
},
data:formData,
}
$http(req).success(cb).error(cbError);
}
my chrome log is
my grails end point
def addComment() {
Comment comment =new Comment()
JSONObject respond = new JSONObject()
comment.content = params.content
comment.PNR = params.PNR
comment.email = params.email
def file = request.getFile('commentFile')
comment.person = Person.findByEmail(params.email);
print file
if (comment.save(flush: true)) {
if (!file) {
CommentFiles files = new CommentFiles()
files.files = new File(file)
files.contentType = uploadedFile.contentType
files.comment = comment
files.save(flush: true)
}
respond.error = false;
respond.message = "comment saved";
response.status = 201;
} else {
print comment.errors.allErrors
respond.error = true;
respond.message = "Could not save comment";
response.status = 409;
}
}
the endpoint have a CORS Interceptor in it, but i'm not 100% sure
please help thanks!
Try without transformRequest: angular.identity,
thanks James Kleeh

Categories

Resources