I am trying to add a customer header in a request angular js for the first time, but am getting the following error
angular.js:10671Error: Failed to execute 'setRequestHeader' on 'XMLHttpRequest': 'x-api-key:' is not a valid HTTP header field name.
Here is my code, at the highest 'app' level:
var movieApp = angular.module('movieApp', ['ngAnimate']);
movieApp.config(['$httpProvider', function ($httpProvider) {
$httpProvider.defaults.headers.common = {
'x-api-key:' : 'key'
};
}])
What am i doing wrong/missing/not understanding? How can I add this header to all (or even one) request?
As the error explains, x-api-key is not a valid HTTP header field. You can go here for the official documentation, or look at wikipedia. To fix this, you have to pass the api key as parameter in the request body.
Related
I'm trying to use instagrams api, without having to authenticate.
if I go to: https://www.instagram.com/explore/tags/chicago/?__a=1
I get a json response.
I'm trying to build an angular 4 provider that returns that data.
getInsta(term){
return this.jsonp.request(this.url+term+'/?__a=1&callback=__ng_jsonp__.__req0.finished')
.map(res => {
console.log(res.json());
});
}
I've tried "callback" and "c". I've tried JSONP_CALLBACK.
I get the error of:
"SyntaxError: Unexpected token ':'. Parse error. - In chicago:1"
and
"JSONP injected script did not invoke callback"
If I click on the unexpected token error, it brings me to the response with all the json data in it. So that means it's coming through, I just cant access it!
Any idea how i can get around this?
Here is a screenshot of the error and when clicking on the error
JSONP is a method to fetch data cross origin, it works because it injects a script tag to the body when the src of the file contains the callback function name.
<script src="http://ani.site.com/api/?callback=myGlobalFunc">
And it assumes that there is a global func on the window with the name myGlobalFunc.
The response of that call gonna look like: myGlobalFunc({data: 'data1'}).
Invocation of the function with one argument which is the data.
In your case, Instagram API return JSON not JSONP.
There for you can't use that mechanism.
I have an Angular app that is accessing a test database. This has worked before, but over the weekend I'm no longer allowed access. I have made no changes to the Angular code. Here's the issue.
For me to access the test database, I have to pass in the username and password since the database is using Basic HTTP Auth. My resource ends up looking like this.
angular.module("CoolApp.misc")
.factory('Ad', ad)
ad.$inject = ['$resource'];
function ad($resource) {
return $resource('http://username:password#build.com/api/advertisement.json');
}
Now when I run
Ad.get({}, function(resp) {}, function(badresp) {console.log(badresp)})
the console spits out the badresp object. I look inside my config headers section and notice this as the url...
url: "http://username#build.com/api/advertisement.json"
Wait a minute, I set the password in as the url. Why is the header not supplying me the password? Is that why I'm receiving a No 'Access-Control-Allow-Origin' header is present on the requested resource. in my console?
For kicks here is my http config
angular.module("CoolApp")
.config(config);
config.$inject = ["$httpProvider"];
function config($httpProvider) {
$httpProvider.defaults.useXDomain = true;
//$httpProvider.defaults.withCredentials = true;
delete $httpProvider.defaults.headers.common["X-Requested-With"];
$httpProvider.defaults.headers.common["Accept"] = "application/json";
$httpProvider.defaults.headers.common["Content-Type"] = "application/json";
}
My question is, what's wrong with this and how do I fix it?
No 'Access-Control-Allow-Origin' header is present on the requested resource. If you say you haven't changed the front-end code since the last time you touched it, then that can only mean that something on the server changed... Based on the error you've provided, it seems like a pretty clear case of somebody either removing the Access-Control-Allow-Origin on the server, or limiting the origins.
You can't change that on the client; that has to change on the server.
I am trying to query the App Store for information on a given app, however I keep getting the following error.
XMLHttpRequest cannot load https://itunes.apple.com/lookup?id=<some-app-id>.
No 'Access-Control-Allow-Origin' header is present on the requested resource.
Origin 'http://www.<some-website>.co.uk' is therefore not allowed access. The response had HTTP status code 501.
The code I'm using to execute the request is as follows.
Does anyone know where I may be going wrong?
var config = {
headers: {
'Access-Control-Allow-Origin': '*',
'Access-Control-Allow-Methods': 'GET',
'Access-Control-Allow-Headers': 'Content-Type, X-Requested-With',
}
};
$http.get("https://itunes.apple.com/lookup?id=<some-app-id>", config).success(
function(data) {
// I got some data back!
}
);
You can use $http.jsonp,
$http.jsonp("https://itunes.apple.com/lookup", {
params: {
'callback': 'functionName',
'id': 'some-app-id'
}
});
Where functionName is the name of your globally defined function in string form. You can redefine it in your module so that it has access to $scope.
Documentation
Edit: here's a plunker showing my successful approach roughly getting it into an AngularJS app:
http://plnkr.co/edit/QhRjw8dzK6Ob4mCu6T6Z?p=preview
Adding those headers to your server won't change what is happening. The cross origin headers need to be added by the iTunes API.
That is not going to happen, so what you need to do instead is to use JSONP style callbacks in your webpage. There is an example on the iTunes search API page.
http://www.apple.com/itunes/affiliates/resources/documentation/itunes-store-web-service-search-api.html
Note: When creating search fields and scripts for your website, you
should use dynamic script tags for your xmlhttp script call requests.
For example:
<script src="https://.../search?parameterkeyvalue&callback="{name of JavaScript function in webpage}"/>
Note the 'callback' parameter there. That is a function defined globally in your javascript on the page that will get called with the response from the request to the url in 'src'. That function puts the data into your page, or application. You'll have to figure out how.
It's a shame that the language used in this documentation is not clearer, because you must do some kind of JSONP style workaround since they don't have CORS enabled on their API.
If you need to dynamically add a script tag (fetching data once is not enough) you can try this tutorial:
Dynamically add script tag with src that may include document.write
The API in general is probably intended for use by backends (not affected by cross origin issues), not for client side fetching.
Using angular 2:
constructor(private _jsonp: Jsonp) {}
public getData(term: string): Observable<any> {
return this._jsonp.request(itunesSearchUrl)
.map(res => {
console.log(res);
});
}
In the latest release of Angular (v1.3.0) they added a fix for the content-type header for application/json. Now all my responses get an error cause they are not valid JSON. I know I should change the back-end to respond with a plain text header, but I can't control that at the moment. Is there any way for me to pre-parse the response before Angular tries to parse it?
i think that this was the fix they made:
https://github.com/angular/angular.js/commit/7b6c1d08aceba6704a40302f373400aed9ed0e0b
The problem I have is that the response I get from the back-end has a protection prefix that doesn't match the one that Angular is checking for.
I have tried to add an http interceptor in the config, but that didn't help, still parses after Angular itself.
$httpProvider.interceptors.push('parsePrefixedJson');
The error i get in my console (it comes from the deserializing of a JSON string in Angular):
SyntaxError: Unexpected token w
at Object.parse (native)
at fromJson ...
You should use
$http.defaults.transformResponse
You also don't wanna use .push(). You need your transformer to do its thing before angular's default transformers. You should use .unshift() instead.
So your code should be
$http.defaults.transformResponse.unshift(transformResponse);
where transformResponse is a function which will transform the response from the server into a proper JSON.
I found a way to change the default transformer by adding this to the Angular app:
app.run(['$http',
function($http) {
var parseResponse = function(response) {
// parse response here
return response;
};
$http.defaults.transformResponse = [parseResponse];
}
]);
This will override the default behavior, you can also set it as an empty array if only selected responses need to be transformed.
See this question/answer: AngularJS, $http and transformResponse
I have a JS/HTML5 Project based on angularjs where I protect the api with an authorization token set in the http header. Now I also want to protect the access to images from the server.
I know how to do it on the server side, but how can I add HTTP Headers to image requests in angular or javascript? For api request we have already added it to the services ($ressource) and it works.
In Angular 1.2.X
There are more than a few ways to do this. In Angular 1.2, I recommend using an http interceptor to "scrub" outgoing requests and add headers.
// An interceptor is just a service.
app.factory('myInterceptor', function($q) {
return {
// intercept the requests on the way out.
request: function(config) {
var myDomain = "http://whatever.com";
// (optional) if the request is heading to your target domain,
// THEN add your header, otherwise leave it alone.
if(config.url.indexOf(myDomain) !== -1) {
// add the Authorization header (or custom header) here
config.headers.Authorization = "Token 12309123019238";
}
return config;
}
}
});
app.config(function($httpProvider) {
// wire up the interceptor by name in configuration
$httpProvider.interceptors.push('myInterceptor');
});
In Angular 1.0.X
If you're using Angular 1.0.X, you'll need to set the headers more globally in the common headers... $http.defaults.headers.common.Authentication
EDIT: For things coming from
For this you'll need to create a directive, and it's probably going to get weird.
You'll need to:
Create a directive that is either on your <img/> tag, or creates it.
Have that directive use $http service to request the image (thus leveraging the above http interceptor). For this you're going to have to examine the extension and set the proper content-type header, something like: $http({ url: 'images/foo.jpg', headers: { 'content-type': 'image/jpeg' }).then(...)
When you get the response, you'll have to take the raw base64 data and set the src attribute of your image element to a data src like so: <img src="data:image/jpeg;base64,9hsjadf9ha9s8dfh...asdfasfd"/>.
... so that'll get crazy.
If you can make it so your server doesn't secure the images you're better off.
As said here you can use angular-img-http-src (bower install --save angular-img-http-src if you use Bower).
If you look at the code, it uses URL.createObjectURL and URL.revokeObjectURL which are still draft on 19 April 2016. So look if your browser supports it.
In order to use it, declare 'angular.img' as a dependency to your app module (angular.module('myapp', [..., 'angular.img'])), and then in your HTML you can use http-src attribute for <img> tag.
For example: <img http-src="{{myDynamicImageUrl}}">
Of course, this implies that you have declared an interceptor using $httpProvider.interceptors.push to add your custom header or that you've set statically your header for every requests using $http.defaults.headers.common.MyHeader = 'some value';
we have the same issue and solve it using a custom ng-src directive ..
basically a secure-src directive which does exactly what ng-src does (its a copy basically) BUT it extends the url with a query parameter which includes the local authentication header.
The server code returning the resources are updated to not only check the header but also the query parameters. of course the token added to the query parameter might be authenticated slightly differently.. e.g. there might be a time window after after a normal rest request in which such a request is allowed etc .. since the url will remain in the browser history.
From oficial documentation at: http://docs.angularjs.org/api/ngResource/service/$resource
Usage
$resource(url, [paramDefaults], [actions]);
[...]
actions: Hash with declaration of custom action that should extend the
default set of resource actions. The declaration should be created in
the format of $http.config:
{action1: {method:?, params:?, isArray:?, headers:?, ...},
action2: {method:?, params:?, isArray:?, headers:?, ...}, ...}
More about $http service:
http://docs.angularjs.org/api/ng/service/$http#usage_parameters
As pointed out Here FIrefox supports httpChannel.setRequestHeader :
// adds "X-Hello: World" header to the request
httpChannel.setRequestHeader("X-Hello", "World", false);
In the example code above we have a variable named httpChannel which
points to an object implementing nsIHttpChannel. (This variable could
have been named anything though.)
The setRequestHeader method takes 3 parameters. The first parameter is
the name of the HTTP request header. The second parameter is the value
of the HTTP request header. And for now, just ignore the third
parameter, and just always make it false.
However this seems to be only available on Firefox (link)
You can either use Cookies to pass the value and retrieve it as a cookie instead of a HttpHeader or use ajax to retrieve the image with a custom header.
More links :
link1
link2