I am totally new to AngularJs. I am trying to send a PATCH request using Angularjs to Django Tastypie API's. My code is
var module = angular.module('myApp', []);
module.config(function ($httpProvider) {
});
function MyController($scope,$http)
{
$scope.patchCall=function(){
$http({
url: "/patchrequest/",
data:data,
method: "PATCH",
})
.success(function(data){
console.log("SUCCESS");
$scope.list = data.items;
}).error(function() {
console.log("FAIL");
});
}
}
But when I am trying to send a request using this code I am Getting an error that http.patch is not a function. Tell me how can i configure ng-app and services to send a PATCH request using AngularJs. I read PATCH request is available in $resource so i tired it with $resource also. But find the same result. Please guide me how can i configure an app from scratch to send CRUD requests, specially PATCH request
Your error doesn't make sense based on the code you're showing, but a common issue with adding PATCH to AngularJS is that it doesn't have a default Content-Type header for that HTTP method (which is application/json;charset=utf-8 for PUT, POST and DELETE). Here's my configuration of the $httpProvider to add patch support:
module.config(['$httpProvider', function($httpProvider) {
$httpProvider.defaults.headers.patch = {
'Content-Type': 'application/json;charset=utf-8'
}
}])
Related
I want to send an api key for every request I make:
function MyService($http) {
var req = {
method: 'GET',
url: 'https://api.giphy.com/v1/stickers/trending',
headers: {
'api_key':'123'
}
}
return $http(req);
}
but the problem is that all requests are OPTIONS (not GET) and is not sending the api_key. Is that the right way to send headers? thanks
Editing because it was marked as duplicate:
This is not a CORS issue. The error I´m getting is 401. That means authentication failed because the endpoint is not receiving the request header with the api_key.
What you did is totally fine, but if the api_key is always different, so you have to provide the api_key value dynamically in order to be added to the request.
If it is always the same, you have a really better way to do that: through interceptors. And you will set that only one time. Again, this method is if you have to set up some parameter which is always the same, so actually it is for doing standard operations over HTTP requests.
First, you need to define your Interceptor:
myApp.service('MyRequestsInterceptor', [function() {
this.request = function(config) {
config.headers.api_key = 'My Default API KEY';
return config;
};
}]);
And then simply add your interceptor to AngularJS $httpProvided:
myApp.config([ '$httpProvider', function($httpProvider) {
$httpProvider.interceptors.push('MyRequestsInterceptor');
} ]);
I have an Ionic App that I am using restangular to communicate with a node express application.
Everything is working when I have the node express application configured to use http.
Ionic App side:
RestangularProvider.setBaseUrl('http://11.22.33.44:3000');
// custom header
interceptors.serialNumber = function (element, operation, what, url, headers, query) {
return {
headers: angular.extend({
'x-serialnumber': deviceStore.serialNumber
}, headers)
};
};
Restangular.one(‘Admin’).get()
.then(function (data) {
console.log(data);
}, function (error) {
console.log(error);
});
Node Express App side:
var app = express();
app.use(cors());
app.get('/Admin, function(req, res) {
console.log(admin-get');
res.send(200);
});
I was expecting I would need to handle a pre-flight request since the cors node module states: “An example of a 'complex' CORS request is one that uses an HTTP verb other than GET/HEAD/POST (such as DELETE) or that uses custom headers.” So I am not sure why this works?
I reconfigure the Ionic App and Node Express App to use a https address instead of a http:
Ionic App side:
RestangularProvider.setBaseUrl('https://11.22.33.44:3000');
// custom header
interceptors.serialNumber = function (element, operation, what, url, headers, query) {
return {
headers: angular.extend({
'x-serialnumber': deviceStore.serialNumber
}, headers)
};
};
Restangular.one(‘Admin’).get()
.then(function (data) {
console.log(data);
}, function (error) {
console.log(error);
});
Node Express App side:
var app = express();
app.use(cors());
app.get('/Admin, function(req, res) {
console.log(admin-get');
res.send(200);
});
when the Ionic App performs the GET request, I see in the Chrome debugger under “Network” an OPTIONS request that gets canceled (request’s status). This tells me that I need to enable cors pre-flight on my Node Express App side (though why didn’t I see this error when the server was configured with http instead of https?).
So I tried the following on the Node Express App side per the express js cors module documentation:
app.options('Admin', cors()); // enable pre-flight request
app.get('/Admin', cors(), function(req, res) {
console.log('admin-get');
res.send(200);
});
I see the same thing in the Chrome debugger under “Network” - a OPTIONS request that gets canceled (request’s status). I also tried
app.options('*', cors());
with the same result.
I then removed the insertion of the custom header (x-serialnumber) on the Ionic App side. It now works.
So why would the Node Express Application work when configured with a http address with out handling a pre-flight request I would expect due to the insertion of a custom header on the Ionic App side?
When the Node Express App is configured with a https address (as well as Ionic App side) why am I not handling the OPTIONS request? Is the way I am configuring cors incorrect? What am I missing?
I think it is a cors issue since I can eliminate the custom header on the Ionic App side when they are configured for a https address and it works.
What do I need to do to get this working?
UPDATE
I tried using Angular JS $http instead of Restangular. I got the following result which works:
$http({
method: 'GET',
url: theUrl
}).then(function successCallback(response) {
$http({
method: 'GET',
url: theUrl,
headers: {
'x-serialnumber' : deviceStore.serialNumber
}
}).then(function successCallback(response) {
}, function errorCallback(response) {
});
}, function errorCallback(response) {
});
I see in Chrome Network Debugger the first GET (minus the custom header) goes out and I get a good response (200), followed by the OPTIONS request where I also get a good response (200), followed by a good GET with the custom header in it (get good response back).
If I do NOT do this first GET request minus the custom header, the OPTIONS request aborts on the Angular JS Ionic App side with a status of -1.
NOTE: I can change out the initial $http request (minus custom header) for a Restangular request (minus custom header)
Why is this initial GET minus the custom header needed (i.e. GET (minus custom header) | OPTIONS | GET (with custom header))?
What do I not understand?
Well what I needed to do was the following:
$http({
method: 'GET',
url: 'https://example.com/DUMMY'
}).then(function successCallback(response) {
$http({
method: 'GET',
url: 'https://example.com',
headers: {
'x-serialnumber': deviceStore.serialNumber
}
}).then(function successCallback(response) {
console.log('SUCCESS');
}, function errorCallback(response) {
console.log('FAILURE');
});
}, function errorCallback(response) {
console.log('FAILURE');
});
In essence, I needed to send a "preliminary" GET request with NO custom header. The GET request could be to anything on my node express server. After this "preliminary" GET request, I could perform the GET request with the custom header in it.
Specifically on the server side I see the following:
GET /DUMMY 200 10ms - 2b
OPTIONS / 204 1ms
GET / 200 13ms - 1.03kb
Without performing this "preliminary" get request, the OPTIONS request in my Ionic App would abort - status code = -1 - usually means the request was aborted and would never leave Ionic App side.
I still do not understand why I need this "preliminary" GET request, but this works for me.
I'm trying to connect my Angular app to the Bluemix QA API. So I have this code.
$http({
method: 'POST',
url: 'https://gateway.watsonplatform.net/question-and-answer-beta/api/v1/question/healthcare',
headers: {
'Content-Type': 'application/json',
'Authorization':'Basic mytoken',
'X-SyncTimeout': 30
},
data: {
'question': {
'questionText': 'Malaria?'
}
}
}).then(function(response){
$scope.response = JSON.stringify(response);
});
Also I have this on my app.js
.config([
'$routeProvider',
'$httpProvider',
function($routeProvider, $httpProvider){
$httpProvider.defaults.headers.common['Access-Control-Allow-Origin'] = '*';
$httpProvider.defaults.headers.common['Access-Control-Allow-Headers'] = '*';
}])
But I'm getting this error when I try to run the method:
Request header field Access-Control-Allow-Origin is not allowed by Access-Control-Allow-Headers.
And if I try to remove the header it'll give me a problem in another header. So, any ideas? Or any ajax example? I know there's a few nodejs examples, but I want to know if it's possible to connect directly to the api.
You are getting this because you are trying to perform cross site scripting. Watson does not support this. You will need to proxy the request to your backend of your app and then have your app funnel the request to Watson.
For example here is an app that works with Personality Insights that funnels the request from Angular to the backend and then to Watson.
I'm creating a web app using AngularJS. To test it, I'm running the app in a NodeJS server, using angular-seed template.
In this app, I need to send a JSON message to another host, via POST request, and get the response, so, I'm using CORS.
My request is done by implementing a service that uses AngularJS http service (I need the level of abstraction that $http provides. So, I don't use $resource).
Here, my code. Please pay attention to the fact that I modify $httpProvider to tell AngularJS to send its requests with the appropriate CORS headers.
angular.module('myapp.services', []).
// Enable AngularJS to send its requests with the appropriate CORS headers
// globally for the whole app:
config(['$httpProvider', function($httpProvider) {
$httpProvider.defaults.useXDomain = true;
/**
* Just setting useXDomain to true is not enough. AJAX request are also
* send with the X-Requested-With header, which indicate them as being
* AJAX. Removing the header is necessary, so the server is not
* rejecting the incoming request.
**/
delete $httpProvider.defaults.headers.common['X-Requested-With'];
}
]).
factory('myService', function($http) {
return {
getResponse: function() {
var exampleCommand = JSON.stringify({"foo": "bar"});
// This really doesn't make a difference
/*
var config = {headers: {
'Access-Control-Allow-Origin':'*',
'Access-Control-Allow-Headers': 'Content-Type, Content-Length, Accept',
'Content-Type': 'application/json'
}
};
*/
//return $http.post(REMOTE_HOST, exampleCommand, config).
return $http.post(REMOTE_HOST, exampleCommand).
success(function(data, status, headers, config) {
console.log(data);
return data;
}).
error(function (data, status, headers, config) {
return {'error': status};
});
}
}
});
The problem is I can't make it work. I always get this error message:
Cross-Origin Request Blocked: The Same Origin Policy disallows reading
the remote resource at REMOTE_HOST. This can be fixed by moving the
resource to the same domain or enabling CORS.
But if I do a simple jQuery AJAX call like this:
$.ajax(REMOTE_HOST,
{
dataType: "json",
type: "POST",
data: exampleCommand,
success: function(data) { console.log(data); },
error: function(request, textStatus, errorThrown) { console.log("error " + textStatus + ": " + errorThrown);}
});
It works fine.
So, my questions:
- How do I allow cross-site requests in an AngularJS running under NodeJS?
UPDATE: Thanks to Dayan Moreno Leon's response.
My problem is I need to add cors support to my server. I'm using NodeJS http-server for development and lighttpd for production.
- Why does the simple jQuery POST request work but AngularJS POST request doesn't?
I guess jQuery AJAX requests are cross-domain by default. Not really sure yet.
Many thanks in advance
CORS is not handled on the client but in the server you need to allow CORS on your nodejs app where your angular app is trying to POST. you can try using cors module if you are using express
https://www.npmjs.org/package/cors
other whise you need to check for the options method and return 200 as a response
http://en.wikipedia.org/wiki/Cross-origin_resource_sharing
Why does the simple jQuery POST request work but AngularJS POST request doesn't?
jQuery uses simple requests while AngularJS uses preflighted requests
In your angular code you can add set Content-Type to application/x-www-form-urlencoded and encode your data using $.param
First, I know this question has been asked several times. I have tried many posted solutions and nothing is working for me..
Here are a few other places this was asked:
How to specify headers parameter for custom Angular $resource action
How can I post data as form data instead of a request payload?
Setting application wide HTTP headers in AngularJS
https://groups.google.com/forum/#!msg/angular/Mtsf-YdwwWo/P_Ui4t_DiXkJ
The attempts:
var app = angular.module('theApp', ['app.services']);
app
.config(['$httpProvider', function ($httpProvider) {
// Try (1): This doesn't work
$httpProvider.defaults.headers.common['Content-Type'] = 'application/json;charset=utf-8';
// Try (2): This doesn't work either
$httpProvider.defaults.headers.post['Content-Type'] = 'application/json;charset=utf-8';
}])
angular.module('app.services', ['ngResource'])
// Resource for Drupal system/connect.post API (via services.module)
.factory('SystemConnect', function($resource, $http) {
// Try (3): There's no way this should work. But what the hell let's try!
$http.defaults.headers.common['Content-Type'] = 'application/json;charset=utf-8';
$http.defaults.headers.post['Content-Type'] = 'application/json;charset=utf-8';
return $resource('api/system/connect.json', {}, {
post: {
method: 'POST',
params: { },
isArray: true,
// Try (4): This doesn't work either
headers: { 'Content-Type': 'application/json;charset=utf-8' }
}
});
});
function SomeCtrl($scope, SystemConnect) {
// FAIL, this results in "406 Not Acceptable: Unsupported content type application/xml"
$scope.user = SystemConnect.post();
}
app.controller('SomeCtrl', SomeCtrl);
It sounds like many people have solved this before. Could someone kindly let me know the right way to do this?
PS: Weirdly, when running this code in Firefox, Angular uses 'Content-Type: text/plain' for the POST!?
I remember reading you have to include content in a post for it to accept your header changes.
$scope.user = SystemConnect.post({});