New to angular, trying to setup a very simple application using the Google Maps / Places API.
I can successfully use the geolocation service with:
.controller('MainCtrl', [
'$scope',
'$http',
function($scope, $http){
$scope.userLocation = [];
$scope.currentLocation = function() {
$http({
method: 'GET',
url: 'https://www.googleapis.com/geolocation/v1/geolocate?key=xxx'
}).then(function successCallback(response) {
$scope.userLocation.push(response);
});
}
}])
Problem:
When I try a similar GET request to their Places API - I get CORS errors:
XMLHttpRequest cannot load https://maps.googleapis.com/maps/api/place/nearbysearch/json?location=36.23…5.1458888&type=bar&key=xxx. No 'Access-Control-Allow-Origin' header is present on the requested resource. Origin 'http://0.0.0.0:3000' is therefore not allowed access.
Question: Am I able to make these types of requests from Angular or do I need to setup the backend to make that call instead?
I tried using JSONP as the method, which passed the CORS issue, but then I have the problem of not being able to access the data. Not sure if it's invalid JSON... but it says Unexpected identifier :, and when I view the source it looks like perfectly fine data to me:
{
"html_attributions" : [],
"results" : [
{
"geometry" : {
"location" : {
"lat" : 36.2388477,
"lng" : -115.1540073
},
},
"icon" : "https://maps.gstatic.com/mapfiles/place_api/icons/restaurant-71.png",
"id" : "578bfba1f17b0c5fbdafd5b71600b50d3e95c1ca",
"name" : "Ruby Tuesday",
"opening_hours" : {
"open_now" : true,
"weekday_text" : []
},
You can use Places API on client side via the library included in Google Maps JavaScript API.
Please refer to this page to figure out how it works:
https://developers.google.com/maps/documentation/javascript/places
Otherwise, you have to create your backend server to send requests to Google and pass response to your client side code.
Hope it helps!
After research I found the below solution. It worked on angular 11.
Some google get api gives CORS issues so to resolve that you need to install below npm package
npm install axios
In the sevice.ts file
const axios = require('axios');
getTimeZone(latitude: any, longitude: any): any {
console.log("lat", latitude);
const url1 =
`https://maps.googleapis.com/maps/api/timezone/json?location=` +
latitude +
"," +
longitude +
`×tamp=1331161200&key=` +
this.googleApiKey;
const config = {
method: "get",
url: url1,
headers: {},
};
return new Observable<any>((observer) => {
axios(config)
.then(function (response: any): void {
observer.next(response.data);
// return response.data;
})
.catch(function (error: any): void {
observer.next(error);
});
});
}
in component.ts file
getTimezoneVal(lat: any, long: any): void {
this.lat = lat;
this.long = long;
this.googleAddressService.getTimeZone(lat, long).subscribe(
(res: any) => {
console.log("res", res);
})
}
In component file you will get response and CORS issue will get resolved....
Thanks....
Vikas Anand
I think JSONP may work in this situation, Jsonp helps for cross domain issues.
Related
I am using Django with Angular JS to access the Google Drive API. I am following this document from Google. The FLOW.step1_get_authorize_url() gives me the URL similar to the sample URL mentioned on the page. But the problem is that after return HttpResponseRedirect(authorize_url) the browser does not redirect to the authorize_url and gives the error as shown in the picture below (Response to preflight request doesn't pass access control check: No 'Access-Control-Allow-Origin' header is present on the requested resource. Origin 'http://127.0.0.1:8000' is therefore not allowed access. The response had HTTP status code 405).
But if I copy pasted the URL, it works fine.
The oauth2 function looks like this.
def index(request):
FLOW = flow_from_clientsecrets(
settings.GOOGLE_OAUTH2_CLIENT_SECRETS_JSON,
scope='https://www.googleapis.com/auth/drive',
redirect_uri='http://127.0.0.1:8000/oauth2callback/'
)
FLOW.params['access_type'] = 'offline'
authorize_url = FLOW.step1_get_authorize_url()
return HttpResponseRedirect(authorize_url)
And here is the oauth2callback function.
def auth_return(request):
credential = FLOW.step2_exchange(request.GET)
return HttpResponseRedirect("/mycustomurl")
I used this to enable CORS in the Django Server Side. Here is my part of service in Angular that makes the call to oauth2.
(function () {
'use strict';
angular.module('myApp')
.service('myService', function ($http) {
this.saveToDrive = function (startYear, endYear, shape) {
var config = {
params: {
start: '1999',
end: '2002',
action: 'download-to-drive'
},
headers: {
'Access-Control-Allow-Origin': '*',
'X-Requested-With': null
}
}
var promise = $http.get('/oauth2/', config)
.then(function (response) {
return response.data;
});
return promise;
};
});
})();
Please suggest what am I missing here. Any help or suggestions are highly appreciated.
I found it be a minor design issue rather than the code issue. I separated the logic that sends the oauth2 request to the client, and after the oauth2 request, I sent request to internal API with the params options. And now it's working fine.
I want to send data from AngularJS to the back end (Django) via Http request.
I tried many ways but I keep not getting the sent data when receiving the request in django.
Before I paste my code, I just have changed the configurations in AngularJS in my project as the following
var myApp = angular.module('myApp',[]).config(['$httpProvider', '$interpolateProvider', function ($httpProvider, $interpolateProvider) {
$interpolateProvider.startSymbol('{/');
$interpolateProvider.endSymbol('/}');
$httpProvider.defaults.headers.post['Content-Type'] = 'application/x-www-form-urlencoded';}]);
The urls:
urlpatterns = [
url(r'^save_comment/', views.save_comment, name='save_comment'),]
Sending Https POST in Angular:
$scope.submit_comment = function () {
$http({
method: "POST",
url: 'save_comment',
data: $.param({
'fish_id' : "1"
})
}).success(function (response) {
console.log(response.result);
}).error(function () {
console.log("failed")
}); }
Receiving the request in the Views
def save_comment(request):
data = request.POST.get('fish_id')
return JsonResponse({'result': data}, content_type="application/json", safe=False)
But I didn't get any result. the console gave me this error:
POST http://127.0.0.1:8000/brain_browser/save_comment 500 (Internal
Server Error)
So what should I do to send Post data from Angular to Django?
Thank in a dvance.
Not an answer but you can debug yourself. Add this to settings.py
LOGGING = {
'version': 1,
'disable_existing_loggers': False,
'handlers': {
'file': {
'level': 'DEBUG',
'class': 'logging.StreamHandler',
},
},
'loggers': {
'django': {
'handlers': ['file'],
'level': 'DEBUG',
'propagate': True,
},
},
}
Your url: 'save_comment' seems to be missing a slash at the beginning, since your url expects http://127.0.0.1:8000/save_comment/ but because of the missing slash you are sending http://127.0.0.1:8000/brain_browser/save_comment.
So change the url in your Javascript to url: '/save_comment/'
Edit: #bobleujr's answer could also fix the problem if csrf tokens are the problem. In my personal Angular/Django project I simply put this at the very top of my javascript:
myApp.config(['$httpProvider', function($httpProvider) {
$httpProvider.defaults.xsrfCookieName = 'csrftoken';
$httpProvider.defaults.xsrfHeaderName = 'X-CSRFToken';
}]);
2nd Edit: This should be the solution
In your views, do this instead of data = request.POST.get('fish_id'):
body_unicode = request.body.decode('utf-8')
data = json.loads(body_unicode)
# Work with "data" from now on, i.e:
print(data["fish_id"])
This is because request.body (Your parameters) is a byte string, and json.loads does not accept byte strings.
Also make sure you have json imported in your views at the very top like so:
import json
trying to call data through openweathermap api
if I call it through 'GET'method.there is
405 (Method Not Allowed)
var req = {
method: 'GET',
url: 'http://api.openweathermap.org/data/2.5/forecast/daily?APPID=' + ApiKey + '&q=London,us',
headers: {
'x-api-key': ApiKey
}
}
$http(req)
.then(function (data) {
console.log(data);
}, function (err) {
console.log(err);
});
#faisal
I ran into this error today, and after some debugging, I realized that it was because I had $httpProvider.defaults.headers.common['X-Requested-With'] = 'HttpRequest'; in my config file. I just disabled CORS for convenience and solved the problem.
This answer is what helped me: Disable CORS in angularJS
Use the params property to encode the search parameters:
var req = {
method: 'GET',
//url: 'http://api.openweathermap.org/data/2.5/forecast/daily?APPID=' + ApiKey + '&q=London,us',
url: 'http://api.openweathermap.org/data/2.5/forecast/daily',
params: { appid: ApiKey, q: 'London,us' }
}
The problem is likely that the &q=London,us is illegal. The comma character needs to be percent-encoded to q=London%2Cus. Use the params property to properly encode the parameters.
Update
I tested it with my APPID (which I am not going to publish) and it worked.
Here is my DEMO on PLNKR with the APPID removed.
In my angular app, I have the following error when I try to make an REST api.
My Code is given below:
Angular Controller
$scope.saveTeam = function() {
var club = {};
club.name = $scope.selectedClub;
var service = API.getService();
service.create( {}, { club: club },
function( res ) {
}, function(err) {
console.log("club err : ", err);
});
}
}
Angular Factory
// Clubs service used for communicating with the coaches REST endpoint
angular
.module('app')
.factory('API', ['$resource', 'session', function($resource, session) {
var mainUrl = '/clubs';
return {
getService : function() {
var token = session.getToken();
return $resource(mainUrl, { }, {
createClub: {
method: 'POST',
url: mainUrl,
isArray: false,
headers: { 'Token': token }
}
})
}
}
});
How can I solve this error? Thanks in Advance.
Install this chrome extension to avoid CORS error. This error generally comes because of the security headers in the request made by a client. Use the line of code shown below before making any request to server.
$http.defaults.headers.post["Content-Type"] = "application/json";
Working principles of CORS is a simple HEADERS game between Client and Server. The browser (the client) set in the Origin key the current domain in your case set "http://localhost:9001". The server, in turn, verified that this value is among those trusted and responds with another piece of information (always in the header) with the key Access-Control-Allow-Origin. If the two values are equal, then the browser uses the response, otherwise you will have an error.
So in the future you need to configure the server but for development you can start the Chrome browser with Disable same origin policy. With disable security the browser don't set the origin and you don't have a problem. This is the problem so check this link:
Disable same origin policy in Chrome
I'm absolutely new to angular.js, so I'm sorry for a such stupid question. But maybe it would help a little bit to other beginers.
I'm learning from a sample project created by someone else, but I'm using a local IIS (instead of IIS Express or VS dev. server). So my base path is http://localhost/SampleProject
The sample project contains this $http.get
$http.get('https://maps.googleapis.com/maps/api/geocode/json',
{
params: params,
headers: { 'Accept-Language': 'en' }
}
)
This works on base URL like "http://localhost:1234", but in my case I get
Failed to load resource: the server responded with a status of 400 (Bad Request)
because request URL is
http://localhost/SampleProject/https://maps.googleapis.com/maps/api/geocode/json?sensor=false
Can anyone tell me why is angular.js prepending base url even if absolute path URL is used?
Thanks,
Tom
Nothing related to $http
From 1.3, Angular does not allow global variable controller.
Here is the working version:
http://plnkr.co/edit/zGj4Ayy8NIplUva86NP6?p=preview
var app = angular.module('myApp', []);
app.controller('customersController',
function($scope,$http) {
var params = { address: "Zlin, Czech Republic", sensor: false };
$http.get("https://maps.googleapis.com/maps/api/geocode/json", {
params: params,
headers: { 'Accept-Language': 'en' }
}).success(function(response) {
$scope.names = response;
});
});
I've solved this issue. It was caused by wrong default URL handling.
I had to add
if (config.url.indexOf('http') !== 0 && config.url.indexOf('//' !== 0))
line into app.js file:
app.config(["$httpProvider", function ($httpProvider) {
$httpProvider.interceptors.push('middleware');
}]);
app.factory('middleware', ['__baseUrl',
function (__baseUrl) {
return {
request: function (config) {
// handle absolute URL request
if (config.url.indexOf('http') !== 0 && config.url.indexOf('//' !== 0))
{
config.url = __baseUrl + config.url
}
return config;
}
};
}]);