Access header's properties within a $http call in AngularJS - javascript

Following github API's documentation for pagination, I'm trying to request event items and retrieve the Link header (just like they suggest) to build the pagination. The problem is that I don't know how to handle the headers('Link') object.
Function:
getEvents: function(page) {
if(cacheService.get('eventos_'+page)) {
return cacheService.get('eventos_'+page);
} else {
var deferred = $q.defer();
$http.get('https://api.github.com/repos/'+owner+'/'+repo+'/events', {params: {per_page: 15, page: page}})
.success(function(events, status, headers) {
console.log(events, status, headers('Link'));
cacheService.put('eventos_'+page, events);
deferred.resolve(events);
}).error(function(err) {
deferred.reject('Error', err);
});
return deferred.promise;
}
}
The resulting "object" (if it can be called like that) is:
"
<https://api.github.com/repositories/XXXXXX/events?page=2&per_page=15>; rel="next",
<https://api.github.com/repositories/XXXXXX/events?page=4&per_page=15>; rel="last"
"
¿How can save page (next and last) numbers in $scope variables? or at least how can I traverse that object?
Don't laugh, but I tried headers('Link').rel['last'] without success, of course.

From the angular $http document https://docs.angularjs.org/api/ng/service/$http
The response object has these properties:
data – {string|Object} – The response body transformed with the transform functions.
status – {number} – HTTP status code of the response.
headers – {function([headerName])} – Header getter function.
config – {Object} – The configuration object that was used to generate the request.
statusText – {string} – HTTP status text of the response.
And to get data from headers its headers['Link'] if you can see 'Link' in your response header
Below is the code to get pagination links from header if you are sending pagination parameters in response header
function parseHeader(header){
// Split parts by comma
var parts = header.split(',');
var links = {};
// Parse each part into a named link
angular.forEach(parts, function (p) {
var section = p.split(';');
if (section.length != 2) {
throw new Error("section could not be split on ';'");
}
var url = section[0].replace(/<(.*)>/, '$1').trim();
var queryString = {};
url.replace(
new RegExp("([^?=&]+)(=([^&]*))?", "g"),
function($0, $1, $2, $3) { queryString[$1] = $3; }
);
var page = queryString['page'];
if( angular.isString(page) ) {
page = parseInt(page);
}
var name = section[1].replace(/rel="(.*)"/, '$1').trim();
links[name] = page;
});
return links;
}

Related

Removing values from array and adding them to POST method request

I have a cart in my AngularJS app and I need to identify the items through their id through a POST method.
They are stored in an array called patent_ids and are appended to the request like so:
var cartArr = [];
var cartItems = ngCart.getItems()
cartItems.forEach(function(currentValue, index, array){
cartArr.push(currentValue._id)
})
var obj = {
patent_id: cartArr
};
fetchBasketPatents(obj);
function fetchBasketPatents(obj) {
//load of code to call service and pass the ids
}
var REST_SERVICE_URI = 'http://localhost:8080/p3sweb/rest-basket/';
factory.fetchBasketPatents = function(ids) {
var deferred = $q.defer();
$http.post(REST_SERVICE_URI, ids) //REQUEST TO BACK END WITH IDS
.then(
function(response){
deferred.resolve(response.data)
},
function(errResponse){
deferred.reject(errResponse)
}
)
return deferred.promise;
}
It works but it would be easier if rather than sending the ids in a named array, they could be sent as an anonymous array, or even better each item extracted an inserted into an anonymous object.
Question
How do I send the ids in the POST request in either an anonymous array or object? Apologies if I am missing something obvious.
How do I send the ids in the POST request in either an anonymous array or object?
From Document:
$http.post('/someUrl', data, config).then(successCallback, errorCallback);
Where data – {string|Object}
So the answer is: you cannot define anonymous array but object only (like you did)

Changing the URL of a Request object from the Fetch API

Say if I have small function that takes a Request object as an argument, and calls the fetch() API.
Except I always want to append something to the url, such as ?foo=bar. I'm curious what the best way would be to go about that.
Example:
function fetchFoo(request) {
request.url += '?foo=bar';
return fetch(request);
}
The issue I have is that this won't work. The Fetch API specification states that the url property read-only.
Is there a way to work around this? I'm thinking I might need to construct an all-new Request object, but I'm unsure what a clever way is to inherit all the options from the previous Request object.
Note that I am able to override any other property by using this syntax:
var originalRequest = new Request('/url');
var overriddenRequest = new Request(originalRequest, { method: 'POST' });
Although it wasn't clear from the docs, it seems that the second init parameter takes precedence over the values passed via the originalRequest parameter. I just can't seem to come up with a way to do this for the url as well.
You could leverage the keys that are on the Request.prototype to build a new Request object in just a few lines.
function newRequest(input, init) {
var url = input;
if (input instanceof Request) {
url = mutateUrl(input.url);
init = init || {};
Object.keys(Request.prototype).forEach(function (value) {
init[value] = input[value];
});
delete init.url;
return input.blob().then(function (blob) {
if (input.method.toUpperCase() !== 'HEAD' && input.method.toUpperCase() !== 'GET' && blob.size > 0) {
init.body = blob;
}
return new Request(url, init);
})
} else {
url = mutateUrl(url);
}
return new Request(url, init);
}
Note the special case for body discussed in this answer.

Reading from NegotiatedContentResult object (sent from WebAPI) in angular js promise

Displayed below is my WebAPI method which returns a list of Information about several books.
[System.Web.Http.Authorize]
public async Task<IHttpActionResult> Get(Guid id)
{
try
{
var result = await _assetAssetRepository.View(id);
if (result == null)
{
return NotFound();
}
return Content(HttpStatusCode.Found, result);
}
catch (Exception ex)
{
return Content(HttpStatusCode.InternalServerError,
"Exception Occurred" + ex.Message + " " + ex.StackTrace);
}
}
Angular js code to consume this data
var getAssetDetails = function (assetId) {
var deferred = $q.defer();
$http.get("/api/Asset/" + assetId, { headers: { 'Authorization': 'Bearer ' + $cookies.get('accessToken') } })
.then(function (response) {
deferred.resolve(response);
}).catch(function (response) {
alert("Oops something wrong: " + response.data);
deferred.reject(response);
}).finally(function () {
});
return deferred.promise;
};
The bit i am struggling is if you replace this line of code in webapi
"return Content(HttpStatusCode.OK,result)" with "return Ok(result)" i can see the data in the UI without any problem. However when i use "return Content(HttpStatusCode.OK,result)", the angular code for some cannot read this and throws out exception and shows the alert message saying "Oops something wrong [object Object]" so it seems like its getting the data but for some reason its still throwing exception. Anyone up for help?
Well, it's best to start with details given by the catch block. But one of many errors can be (which I first had):
Unexpected token R in JSON at position 0
which is be due to responseType: 'JSON' added in your http request. Angular takes the response as JSON where in this case it is not. So we need to remove this.
Here is how I do it (end-to-end). From my API:
return Content(HttpStatusCode.<statuscode>, "ResponseContent: " + "my_custom_error");
Second Case:
//If I'm getting output from another API/Layer then I pass it's output like this
var output = response.Content.ReadAsStringAsync().Result;
return Content(response.StatusCode, "ResponseContent: " + output);
And in the Angular code, I read it like this:
$http({ method: methodType, url: endpoint })
.then(function (response) {
response.status; //gets you the HttpStatusCode to play with
response.data; //gets you the ReponseContent section
}, function (response) {
response.status; //gets you the HttpStatusCode
response.data; //gets you the ReponseContent section
});
From https://docs.angularjs.org/api/ng/service/$http
The response object has these properties:
data – {string|Object} – The response body transformed with the
transform functions.
status – {number} – HTTP status code of the response.
headers – {function([headerName])} – Header getter function.
config – {Object} – The configuration object that was used to
generate the request.
statusText – {string} – HTTP status text of the response.

How to retrieve HttpResponseMessage FileName in JavaScript

I've this WebAPI method, that takes a custom object MyType as input and generate a PDF based on that. The PDF-file is returned as a HttpResponseMessage. Note that I specify the filename on response.Content.Headers.ContentDisposition.FileName:
ASP.NET WebAPI
[Route("")]
public HttpResponseMessage Get([FromUri]MyType input)
{
var pdfContent = PdfGenerator.Generate(input);
var response = new HttpResponseMessage(HttpStatusCode.OK);
response.Content = pdfContent;
response.Content.Headers.ContentDisposition = new System.Net.Http.Headers.ContentDispositionHeaderValue("attachment");
response.Content.Headers.ContentDisposition.FileName = "MyCustomFileName.pdf"
return response;
}
In AngularJS I fetch the file using FileSaver.js like this:
$http.get("api/pdf/", {
params: {
"type": myObject
},
responseType: 'arraybuffer'
}).then(function (results) {
var data = results.data;
var file = new Blob([data], { type: 'application/pdf' });
saveAs(file, 'filename.pdf');
}, function (results) {
console.log(results);
});
It works as excepted, but I'm defining the filename both on WebAPI and in the JavaScript. Is there a way, that I can retrieve the FileName defined in WebAPI in the results variable in JavaScript?
The promise returned by methods of $http are passed as argument an object with the following properties (ref):
data – {string|Object} – The response body transformed with the transform functions.
status – {number} – HTTP status code of the response.
headers – {function([headerName])} – Header getter function.
config – {Object} – The configuration object that was used to generate the request.
statusText – {string} – HTTP status text of the response.
So results.headers('Content-Disposition') will gives you the value of the Content-Disposition header. You will have to do some trivial parsing to get to the actual filename.

dojoJS Solr connector - pass out (return) data

I am new to accessing json data from rest services like Solr and ElasticSearch with JS and the dojo framework.
In this case I have used dojo to write solr.js which contains a simple function that uses JSONP params with dojo.io.script to connect to a Solr index. Now I need to get the function to pass out (return) the data that gets from Solr. This is how I want to call the function:
<script src="solr.js"></script>
<script>
var mySolrData = solrStore(
"http://solrUrl/",
"indexName/select"
);
</script>
This is the code for the solr.js file that contains the function I am calling:
dojo.require("dojo.io.script");
function solrStore (indexURL, collectionPath, wt, rows, start, q) {
//set some default values//
wt = typeof wt !== 'undefined' ? wt : 'json';
rows = typeof rows !== 'undefined' ? rows : '25';
start = typeof start !== 'undefined' ? start : '1';
q = typeof q !== 'undefined' ? q : '*';
//arguments for jsonp to connect to solr index//
var jsonpArgs =
{
url: indexURL + collectionPath,
labelAttribute:"solr",
handleAs: "json",
callbackParamName: "json.wrf",
content: {
wt: wt,
rows: rows,
start: start,
q: q
//end content vars//
},
//load the data
load: function(data){
//set the value of the raw response data
var mySolrStore = data;
//view the data in the console
console.log(mySolrStore.response.docs);
return mySolrStore.response;
//end load data//
},
//on error show in the console
error: function(error){
console.log("An error occured connecting to the Solr index: " + error);
//end on error
}
//end arguments for jsonp
};
//get the data with dojo.io.script.get
dojo.io.script.get(jsonpArgs);
}
When I execute the code in the browser I see the data that need in the console log when it hits the load: part. However, I am having a brain-fart on how I can pull that data out of the function into the page where I call the function because no matter how I try it says it is undefined.
What am I missing that I need to do to get the data I retrieve from the solrStore function into the mySolrData var?
The variable mySolrStore is defined inside the asynchronous function "load:".
If I am not wrong you cannot return(catch values) from an asynchronous function since the context is different.
//set the value of the raw response data
var mySolrStore = data;
I would suggest that you define the variable outside the "load:". For instance you could define it before and
var mySolrStore;
//arguments for jsonp to connect to solr index//
var jsonpArgs = .....
and set the data value inside the load: call.
load: function(data){
//set the value of the raw response data
mySolrStore = data;
Hope it solves issue.

Categories

Resources