Angular http.get charset - angularjs

I'm having some trouble getting my angular application to parse my json-data correctly.
When my json-feed contains e.g. { "title": "Halldórsson Pourié" }
my application shows Halld�rsson Pouri�
I figure the problem is the charset, but i can't find where to change it.
Currently i am using ng-bind-html and using $sce.trustAsHtml(), and I'm very sure the problem occurs when $http.get(url) parses my json.
So how do i tell $http.get(url) to parse the data with a specific charset?

I had a similar issue and resolved it by using:
encodeURIComponent(JSON.stringify(p_Query))
where p_Query is a JSON containing the details of the request (i.e. your { "title": "Halldórsson Pourié" }).
EDIT:
You may also need to add to the header of your GET request the following:
'Content-Type': 'application/x-www-form-urlencoded ; charset=UTF-8'

Had same problem with accented characters and some scientific notation in text/JSON fields and found that AngularJS (or whatever native JavaScript XHR/fetch functions it is using) was flattening everything to UTF-8 no matter what else we tried.
The other respondent here claimed that UTF-8 should somehow still be accommodating your extended character set, but we found otherwise: taking samples of the source data directly, we loaded it into text editor with different encodings and UTF-8 would still squash extended characters to that � placeholder.
In our case, the encoding was ISO-8859-15 but you may be sufficient with ISO-8859-1.
Try adding this $http configuration to your $http.get() call, accordingly:
$http.get(url, {
responseType: 'arraybuffer',
transformResponse: function(data) {
let textDecoder = new TextDecoder('ISO-8859-15'); // your encoding may vary!
return JSON.parse(textDecoder.decode(data));
}
});
This should intercept AngularJS default response transformation and instead apply the function here. You will, of course, want to consider adding some error handling, etc.
If there are better ways to do this without a custom transformResponse function, I have yet to find anything in the AngularJS documentation.

$http.get(url, {responseType: 'arraybuffer', }).then(function (response) { var textDecoder = new TextDecoder('ISO-8859-1'); console.log(textDecoder.decode(response.data));});
This code will replace all your � placeholders into normal characters.

Related

How to create a Perl API to pass data back to an angularjs $http request?

I'm using angular 1.5.7 and perl 5.16.2. I don't have the ability to use any external libraries or switch tools - I'm stuck just using what's included with these two.
The angular controller is making calls to a perl file. I'm able to make POST requests successfully, and my GET requests are returning status 200 but aren't showing the data that I am expecting to see. Right now I'm just working with a simple example to try and narrow down where things are going wrong, and I think I just don't know the format to return values from the perl file.
My controller GET method looks like so:
$http({
method : "GET",
url : "filename.pl",
params:{}
}).then(function successCallback(response) {
console.log(response.records);
}, function errorCallback(response) {
console.log(response);
});
and the perl code being called in filename.pl is:
my $string = q{{"records":{"2":{"City":"México D.F.","Country":"Mexico","Name":"Ana Trujillo Emparedados y helados"},"1":{"Name":"Alfreds Futterkiste","Country":"Germany","City":"Berlin"}}}};
return $string;
The string is just a dummy variable to see if passing things back works - it won't be the final data. I have verified it is valid JSON as well. Here's what the response from the server looks like:
{"data":"","status":200,"config":{"method":"GET","transformRequest":[null],"transformResponse":[null],"url":"glwizardutils.esp","params":{"FUNCTION":"initcheckboxes","CONTEXTID":"432"},"headers":{"Accept":"application/json, text/plain, */*"}},"statusText":"OK"}
The data field is totally blank, and the response field doesn't work at all. I can verify it's hitting the perl file - like I said, POST requests work fine and I included some printouts that verify it's in the correct method, but it's just not returning anything. What should I be doing here instead to get this to work?
If filename.pl is invoked with HTTP, then it should be writing an HTTP response to standard output. At a minimum:
print "HTTP/1.1 200 OK\n";
print "Content-type: application/json\n";
print "\n";
my $string = q{{"records":{"2":{"City":"México ..."}}}};
print $string;
Several frameworks and modules exist in Perl and virtually every other language to handle the repetitive aspects of writing a proper response, which you will want to look into as your Perl server-side script gets more demanding.

AngularJS $http GET comma separated query string parameters

I'm trying to do a HTTP GET call using Angular's $http. I've written a generic function like this,
function doGETRequest(url, params) {
return $http({
method: 'GET',
url: baseURL + url,
headers: {
'Authorization': 'Bearer ' + access_token
},
params: params
});
}
I want to create a URL like this,
https://content.googleapis.com/drive/v2/about?fields=quotaBytesTotal%2CquotaBytesUsed%2CrootFolderId%2Cuser but I cannot for the life of me figure out the query param part. So far I tried the following:
doGETRequest('/about', {fields:'user,quotaBytesTotal,quotaBytesUsed,rootFolderId'})
doGETRequest('/about', {fields:['user','quotaBytesTotal','quotaBytesUsed','rootFolderId']})
doGETRequest('/about', {fields:encodeURIComponent('user,quotaBytesTotal,quotaBytesUsed,rootFolderId')})
It does work for the second one, but it parses it as https://content.googleapis.com/drive/v2/about?fields=user&fields=quotaBytesTotal&fields=quotaBytesUsed&fields=rootFolderId and Google just sends response for the first query and ignores the rest (as expected).
So the question is how do I pass comma separated values in query params? Do I have to manually write URL encoded values? Doesn't this beat the purpose of having a params field?
Okay, for those who stumbled upon the same problem as I did, I found two ways of solving this.
First, as #kiro112 suggested in the comments, I write the params directly in the URL. Since $http doesn't encode the URL it'll work. So the code will be something like
doGETRequest('/about?fields='+encodeURIComponent("user,quotaBytesTotal,quotaBytesUsed,rootFolderId"))
and we'll have to get rid of the params part in the doGetRequest() method. Personally, I don't like this one as it beats the purpose of having the params part in $http.
Second method is overriding the default $httpParamSerializer and supplying our own. To do that, the doGetRequest() method has to be modified like so,
function doGETRequest(url, params) {
return $http({
method: 'GET',
url: baseURL + url,
headers: {
'Authorization': 'Bearer ' +access_token
},
params: params,
paramSerializer: function (value){
return Object.keys(value)+'='+encodeURIComponent(Object.values(value));
}
});
}
What happens here is, we do not let angular encode the params. Let me tell you why. As per the docs here, angular only does encoding like so,
{'foo': 'bar'} results in foo=bar
{'foo': Date.now()} results in foo=2015-04-01T09%3A50%3A49.262Z (toISOString() and encoded representation of a Date object)
{'foo': ['bar', 'baz']} results in foo=bar&foo=baz (repeated key for each array element)
{'foo': {'bar':'baz'}} results in foo=%7B%22bar%22%3A%22baz%22%7D" (stringified and encoded representation of an object)
Whereas we require something in the lines of {'foo':['bar', 'baz']} resulting in foo=bar%2Cbaz. So we override the paramSerializer and write our own serializer.
The second approach looks much cleaner to me as far as using generic methods is concerned. However, I am still on a look out for a better option.

I am uploading the image file in Angular Js to call the java api but my form data is not hitting the api

controller:
$scope.fileToUpload = function(input) {
if (input.files && input.files[0]) {
CommonService.uploadContactImage.upload({
fileName : input.files[0].name
}, input.files[0], function(data) {
});
}
}
Service:
uploadContactImage:function(input){
console.log("game image");
var req = $http({method: 'POST', url: options.api.base_url + '/gameimageupload/',
dataType: 'json', headers: {'Content-Type': undefined}})
.success(function (data)
{
console.log("data" + data);
return data;
});
If you take a good look at your code you will see that there are quite a few things wrong with it. For example, you have defined in your service an uploadContactImage function which takes a single Javascript object as argument (input), while in your controller you attempt to call CommonService.uploadContactImage.upload(...) instead of CommonService.uploadContactImage(...). Additionally, even if the uploadContactImage function was called correctly it doesn't actually do anything with its argument, ie. the input object is never used in the function body.
These issues aside you cannot submit a file to the server just by adding it to the body of a POST request the way you (seem to be) trying to do. Without going into too much detail here, in order to upload a file from the browser a request with content type multipart/form-data needs to be submitted, which will contain your file as well as the necessary HTTP headers for the server to identify it and parse it correctly. I suppose you could try and construct this request yourself, however it's not a task for the faint-hearted. What I would suggest instead is to use one of the many file upload modules available for Angular.js. A Google search will give you quite a few modules that you can check out to see which better fits your needs.

Encoding rest path variable in angularjs

I am having a peculiar issue.
I am calling a restful service with path param from angularjs controller/service.
Below is the url format
/payment/{id}/credit/{creditId}/fetch/options
Now, creditId has special charachters in it for eg 'abcd%xyz-433'
I am calling a service which makes a GET rest call as below in angualarjs controller
creditService.creditOption('abc','abcd%xyz-433').success(function(data, status) {
$log.log('log the status ' + status);
});
The service is as below
creditOption: function(id, creditId) {
return $http({
method: 'GET',
url: '/payment/'+id+'/credit/'+creditId+'/fetch/options'
});
}
The Restful service signature is as follows
#RequestMapping(method = RequestMethod.GET, value = "/payment/{id}/credit/{creditId}/fetch/options", produces = APPLICATION_JSON)
public boolean getCreditOption(#PathVariable String id, #PathVariable String creditId) {
return true
}
This is giving me 404 all the time i execute this code. But when i remove the special charachters it works fine and hits the restful service. I also tried to use encodeURIComponent() and then send the value.. but it is still the same case.
Please let me know if there is any way out for this.
Thanks for any help
The % symbol is used for encoding values in URls, see rfc3986 section 2.1. In particular it's expected that there will be two hex digits after the % - which it seems like you are exactly stumbling on to.
You may have to escape the percent (use %25) or choose a different character to substitute.
You can try it on this page, the address is:
http://stackoverflow.com/questions/27641286/encoding-rest-path-variable-in-angularjs
A 1 percent encoded is %31, so you could just as easily go here:
http://stackoverflow.com/questions/2764%31286/encoding-rest-path-variable-in-angularjs

Angular does not encode the semi-colon character in an url

We need an encoded semi-colon character in our url parameter but angular does not encode this character.
The resource we use looks something like this:
app.factory('TestResource', ['$resource', function ($resource) {
return $resource('http://somedomain.com');
}]);
app.run(['TestResource', function (TestResource) {
TestResource.query({
q: 'sin;sout'
});
}]);
This is the result we get:
http://somedomain.com/?q=sin;sout
We want the url to be:
http://somedomain.com/?q=sin%3Bsout
But if we pre-encode the parameter before sending the % char get's encoded like this:
http://somedomain.com/?q=sin%253Bsout
How can we get the desired result? (http://somedomain.com/?q=sin%3Bsout)
Angular uses its own function to encode the URL. And that function doesn't encode characters that usually don't need to be encoded like / or ?. ; is such a character, too. It's used in matrix URIs, e.g. So Angular's behavior actually conforms to the standard, but it could be a problem when such characters are used literally, i.e. without a special meaning. That seems to be the case here.
Since the URL is build just before sending the request, there's not much we can do. There is kind of a loophole though: Only parameters are encoded, not the base URL. So any workaround would involve creating the URL or at least a part of it yourself.
You could add an interceptor, that adds the properly encoded parameters to the URL before Angular does it. You could even completely replace Angular's behavior that way.
UPDATE:
Another solution came to my mind. The $http service delegates sending the actual request to the $httpBackend service which receives the already constructed URL. Using a decorator you can replace either the ; or the incorrectly encoded %253B with %3B right before the request is sent:
app.config(function($provide) {
$provide.decorator('$httpBackend', function($delegate) {
return function(method, url, post, callback, headers, timeout, withCredentials, responseType) {
url = url.replace(';', '%3B');
$delegate(method, url, post, callback, headers, timeout, withCredentials, responseType);
};
})
});
Building on zeroflagL's answer one could consider changing the replace to change all occurrences of the semi-colon (as it is written it will only replace the first semi-colon):
url = url.replace(/;/g, '%3B');
There is a closed issue for this https://github.com/angular/angular.js/issues/9224
path: Don't escape semicolons. Breaks matrix parameters, and no evidence that Angular's current behavior is problematic.
query: Escaping the entire query string would be unwise, as it breaks an established (albeit archaic) expectation for servers to be able to handle semicolon-delimited query strings.
query values: Probably safe to escape, especially if the server interprets semicolons as query delimiters. Passing complex data types (ie. JSON) via query parameters is a bad idea, but "real-world" string values often contain semicolons, and it seems like a good idea to escape them.
I'll go with zeroflagL's answer but only changing the query values. Like this:
$provide.decorator('$httpBackend', function($delegate) {
return function(method, url, post, callback, headers, timeout, withCredentials, responseType) {
var a = document.createElement('a');
a.href = url;
if(a.search.length > 1) {
var params = a.search.substring(1).split('&');
for (var i=0; i<params.length; i++) {
var param = params[i].split('=');
if(param[1]) {
params[i] = [param[0], param[1].replace(';', '%3B')].join('=');
}
}
url = url.substring(0, url.lastIndexOf('?')) + '?' + params.join('&');
}
$delegate(method, url, post, callback, headers, timeout, withCredentials, responseType);
};
});
You can use encodeURIComponent() method:
q: encodeURIComponent('sin;sout')

Resources