Implement request as JSON for google geolocation API - json

I'm trying to implement google geolocation API in order to get a location by providing the cell data. Would like to make a form where you put in the cell info and get its location.
Here's the page i'm following: https://developers.google.com/maps/documentation/geolocation/intro
I have MNC, MCC, CID, but I really can't understand how to set up a form in HTML that POST a request, with the body in JSON.
Can anyone post me an example please?
Thanks!!

i wrote a python script that return the GPS location of a cell. it uses Google Geolocation API, if there is no result, it looks up the coordinates using OpenCellID API.
#!/bin/python
"""
Written by Atissonoun - Credits to MFC & HAC
***You need to initialize the script in order to fix the import and the dependency.
This is only a Beta version of the project***
This python file works as the engine for the project.
imports, coordinates, run......
"""
#Importing modules
import requests
#defining a Api_Keys
Google_API_KEY="Your google API Key goes here"
OpenCell_Api_Key ="Your OpenCellID API Key goes here"
def Google(MMC,MNC,LAC,ID,API_KEY=Google_API_KEY):
url = "https://www.googleapis.com/geolocation/v1/geolocate?key={}".format(API_KEY)
data={
"radioType": "gsm",
"cellTowers":[
{
"cellId": ID,
"locationAreaCode": LAC,
"mobileCountryCode": MMC,
"mobileNetworkCode": MNC
}
]
}
response = requests.post(url, json=data)
if response.status_code == 200 :
lat=response.json()[u'location'][u'lat']
long = response.json()[u'location'][u'lng']
d={'LAT':lat,'LONG':long}
print('Located Cell: {}'.format(ID))
return d
else:
print('Error: {}'.format(response.status_code))
return None
def Opencell(MMC,MNC,LAC,ID,API_KEY=OpenCell_Api_Key):
url = "https://us1.unwiredlabs.com/v2/process.php"
data = {
"token": API_KEY,
"radio": "gsm",
"mcc": MMC,
"mnc": MNC,
"cells": [{
"lac": LAC,
"cid": ID
}]
}
response = requests.post(url, json=data)
if response.status_code == 200:
if response.json()[u'status']== 'error':
print('Error: {}'.format(response.json()[u'message']))
return None
else:
lat = response.json()[u'lat']
long = response.json()[u'lon']
d = {'LAT': lat, 'LONG': long}
print('Located Cell: {}'.format(ID))
return d
else:
print('Error: {}'.format(response.status_code))
return None

Related

Google Places Detail Not Returning Websites

I'm trying to utilize Google's Place Detail API to return business websites. Here is the code I am running, but I've been unsuccessful across multiple tests with different Place IDs.
import requests
import json
params = {
'place_id': 'ChIJIR7nCYMvXIgRe6yefY5IfWQ',
'fields': 'website',
'key': 'API_KEY',
}
response = requests.get('https://maps.googleapis.com/maps/api/place/details/json', params=params)
data = json.loads(response.content)
print(data)
The output reads:
{'html_attributions': [], 'result': {}, 'status': 'OK'}
What am I doing wrong? Am I using the wrong API?

i am getting an error while running the below code:

The program will prompt for a location, contact a web service and retrieve JSON for the web service and parse that data, and retrieve the first place_id from the JSON. A place ID is a textual identifier that uniquely identifies a place as within Google Maps.
API End Points
To complete this assignment, you should use this API endpoint that has a static subset of the Google Data:
http://py4e-data.dr-chuck.net/json?
need to find Place id for :American University in Cairo
import json
import urllib
serviceurl = "http://py4e-data.dr-chuck.net/json?"
data_address = "American University in Cairo"
address_wanted = data_address
parameters = {"sensor": "false", "address": address_wanted}
paramsurl = urllib.parse.urlencode(parameters)
queryurl = serviceurl + paramsurl
print("DATA URL: ", queryurl)
data = urllib.request.urlopen(queryurl).read().decode()
print('Retrieved', len(data))
jsondata = json.loads(str(data))
print (json.dumps(jsondata, indent = 4))
place_id = jsondata["results"][0]["place_id"]
print("PLACE ID: ", place_id)

Using GraphQL machinery, but return CSV

A normal REST API might let you request the same data in different formats, with a different Accept header, e.g. application/json, or text/html, or a text/csv formatted response.
However, if you're using GraphQL, it seems that JSON is the only acceptable return content type. However, I need my API to be able to return CSV data for consumption by less sophisticated clients that won't understand JSON.
Does it make sense for a GraphQL endpoint to return CSV data if given an Accept: text/csv header? If not, is there a better practise way to do this?
This is more of a conceptual question, but I'm specifically using Graphene to implement my API. Does it provide any mechanism for handling custom content types?
Yes, you can, but it's not built in and you have to override some things. It's more like a work around.
Take these steps and you will get csv output:
Add csv = graphene.String() to your queries and resolve it to whatever you want.
Create a new class inheriting GraphQLView
Override dispatch function to look like this:
def dispatch(self, request, *args, **kwargs):
response = super(CustomGraphqlView, self).dispatch(request, *args, **kwargs)
try:
data = json.loads(response.content.decode('utf-8'))
if 'csv' in data['data']:
data['data'].pop('csv')
if len(list(data['data'].keys())) == 1:
model = list(data['data'].keys())[0]
else:
raise GraphQLError("can not export to csv")
data = pd.json_normalize(data['data'][model])
response = HttpResponse(content_type='text/csv')
response['Content-Disposition'] = 'attachment; filename="output.csv"'
writer = csv.writer(response)
writer.writerow(data.columns)
for value in data.values:
writer.writerow(value)
except GraphQLError as e:
raise e
except Exception:
pass
return response
Import all necessary modules
Replace the default GraphQLView in your urls.py file with your new view class.
Now if you include "csv" in your GraphQL query, it will return raw csv data and then you can save the data into a csv file in your front-end. A sample query is like:
query{
items{
id
name
price
category{
name
}
}
csv
}
Remember that it is a way to get raw data in csv format and you have to save it. You can do that in JavaScript with the following code:
req.then(data => {
let element = document.createElement('a');
element.setAttribute('href', 'data:text/csv;charset=utf-8,' + encodeURIComponent(data.data));
element.setAttribute('download', 'output.csv');
element.style.display = 'none';
document.body.appendChild(element);
element.click();
document.body.removeChild(element);
})
This approach flattens the JSON data so no data is lost.
I have to implement the functionality of exporting list query into a CSV file. Here is how I implement extending #Sina method.
my graphql query for retriving list of users (with limit pagination) is
query userCsv{
userCsv{
csv
totalCount
results(limit: 50, offset: 50){
id
username
email
userType
}
}
}
Make CustomGraphQLView view by inheriting from GraphQLView and overide dispatch function to see if query has a csv also make sure you update graphql url pointing to this custom GraphQLView.
class CustomGraphQLView(GraphQLView):
def dispatch(self, request, *args, **kwargs):
try:
query_data = super().parse_body(request)
operation_name = query_data["operationName"]
except:
operation_name = None
response = super().dispatch(request, *args, **kwargs)
csv_made = False
try:
data = json.loads(response.content.decode('utf-8'))
try:
csv_query = data['data'][f"{operation_name}"]['csv']
csv_query = True
except:
csv_query = None
if csv_query:
csv_path = f"{settings.MEDIA_ROOT}/csv_{datetime.now()}.csv"
results = data['data'][f"{operation_name}"]['results']
# header = results[0].keys()
results = json_normalize(results)
results.to_csv(csv_path, index=False)
data['data'][f"{operation_name}"]['csv'] = csv_path
csv_made = True
except GraphQLError as e:
raise e
except Exception:
pass
if csv_made:
return HttpResponse(
status=200, content=json.dumps(data), content_type="application/json"
)
return response
Operation name is the query name by which you are calling. In previous example given it is userCsv and it is required because the final result as a response came with this key. Response obtained is django http response object. using above operation name we check if csv is present in the query if not present return response as it is but if csv is present then extract query results and make a csv file and store it and attach its path in response.
Here is the graphql schema for the query
class UserListCsvType(DjangoListObjectType):
csv = graphene.String()
class Meta:
model = User
pagination = LimitOffsetGraphqlPagination(default_limit=25, ordering="-id")
class DjangoListObjectFieldUserCsv(DjangoListObjectField):
#login_required
def list_resolver(self, manager, filterset_class, filtering_args, root, info, **kwargs):
return super().list_resolver(manager, filterset_class, filtering_args, root, info, **kwargs)
class Query(graphene.ObjectType):
user_csv = DjangoListObjectFieldUserCsv(UserListCsvType)
Here is the sample response
{
"data": {
"userCsv": {
"csv": "/home/shishir/Desktop/sample-project/media/csv_2021-11-22 15:01:11.197428.csv",
"totalCount": 101,
"results": [
{
"id": "51",
"username": "kathryn",
"email": "candaceallison#gmail.com",
"userType": "GUEST"
},
{
"id": "50",
"username": "bridget",
"email": "hsmith#hotmail.com",
"userType": "GUEST"
},
{
"id": "49",
"username": "april",
"email": "hoffmanzoe#yahoo.com",
"userType": "GUEST"
},
{
"id": "48",
"username": "antonio",
"email": "laurahall#hotmail.com",
"userType": "PARTNER"
}
]
}
}
}
PS: Data generated above are from faker library and I'm using graphene-django-extras and json_normalize is from pandas. CSV file can be download from the path obtained in response.
GraphQL relies on (and shines because of) responding nested data. To my understanding CSV can only display flat key value pairs. This makes CSV not really suitable for GraphQL responses.
I think the cleanest way to achieve what you want to do would be to put a GraphQL client in front of your clients:
+------+ csv +-------+ http/json +------+
|client|<----->|adapter|<----------->|server|
+------+ +-------+ +------+
The good thing here is that your adapter would only have to be able to translate the queries it specifies to CSV.
Obviously you might not always be able to do so (but how are you making them send GraphQL queries then). Alternatively you could build a middleware that translates JSON to CSV. But then you have to deal with the whole GraphQL specification. Good luck translating this response:
{
"__typename": "Query",
"someUnion": [
{ "__typename": "UnionA", "numberField": 1, "nested": [1, 2, 3, 4] },
{ "__typename": "UnionB", "stringField": "str" },
],
"otherField": 123.34
}
So if you can't get around having CSV transported over HTTP GraphQL is simply the wrong choice because it was not built for that. And if you disallow those GraphQL features that are hard to translate to CSV you don't have GraphQL anymore so there is no point in calling it GraphQL then.

AWS API Gateway Malformed Lambda Response

The documentation states that the json should return containing a body,headers,and a status code all of which I have. However for whatever reason when I test it in API gateway it returns a malformed response.
This is the output of the method below it.
"{\"body\": 200, \"headers\": {\"Content-type\":
\"application/json\"}, \"statusCode\": 200}"
def addnumbers(message, context):
result = message['num1'] + 1
print(result)
resp = {
"statusCode": 200,
"body": result,
"headers": { "Content-type": "application/json"}
}
return (json.dumps(resp))
I am currently passing in num1=1 and it doesn't give any better error message. Any guidance would be appreciated.
Ok buckle in for an answer.
Make sure you have proxy integration enabled on whatever resource you want in your API.
Now go to your lambda. Look at how I was previously trying to pass in num1.I was trying to get it from the "Event" or message. This is where I was tripping up. Also note (you can't do a get with a body)
Rather the input to the lambda should be like this.
{
"queryStringParameters": {
"input": "Whatever the input is you want the lambda to test"
}
}
So now that we have our test configured for the lambda we need to code the lambda itself.
I put this code within :
def lambda_handler(event, context):
number = "Hello, " + event['queryStringParameters']['input']
out = {}
out['statusCode'] = 200
out['body'] = number
return (out)
Now if you test it should be fine.
Go back to the API Gateway
In the "Query Strings" Section put in input=randomname
It should now return with hello, randomname

Tornado POST request not detecting json input as argument

I have written a service which takes a json as input. I am using the website hurl.it to send post requests to check. Below is my code snippet:
class BatchSemanticSimilarityHandler(tornado.web.RequestHandler):
def post(self):
self.set_header('Access-Control-Allow-Origin', '*')
self.set_header('Access-Control-Allow-Credentials', 'true')
self.set_header('Access-Control-Allow-Methods', 'GET, POST, PUT, DELETE, OPTIONS')
self.set_header('Access-Control-Allow-Headers','Origin, Accept, Content-Type, X-Requested-With, X-CSRF-Token')
data = json.loads(self.request.body)
apikey = data["apikey"]
try:
UA = self.request.headers["User-Agent"]
except:
UA = "NA"
if bool(usercoll.find_one({"apikey":apikey})) == True:
sentence = data["sentence"]
sentence_array = data["sentence_array"]
n = data["num_of_results"]
if sentence is None or sentence_array is [] or apikey is None or n is None:
self.set_status(200)
output = {"error":[{"code":334,"message":"Bad Input data"}]}
misscoll.insert({"apitype":"batchsemanticsimilarity","timestamp":datetime.datetime.now(), "ip":self.request.remote_ip, "useragent":UA, "uri":self.request.uri,"apikey":apikey, "output":output, "input":{"s1":sentence,"s2":sentence_array}})
self.write(output)
return
results = nb.get_similar(sentence, sentence_array, apikey, n)
print "results is",results
output = {"similar_sentences": results, 'credits':'ParallelDots'}
hitscoll.insert({"apitype":"batchsemanticsimilarity","timestamp":datetime.datetime.now(), "ip":self.request.remote_ip, "useragent":UA, "uri":self.request.uri,"apikey":apikey, "output":output, "input":{"s1":sentence,"s2":sentence_array}})
self.write(output)
return
else:
rejectcoll.insert({"apitype":"batchsemanticsimilarity","apikey":apikey,"timestamp":datetime.datetime.now(), "ip":self.request.remote_ip, "useragent":UA, "url":self.request.uri})
self.write({"error":[{"code":333,"message": "Bad Authentication data"}]})
return
The json that I am giving as the body of the request is as below:
{
"sentence": "BJP leads in Bengaluru civic body`s poll, all eyes on JD(S)",
"sentence_array": [
"Narendra Modi is the prime minister",
"Sonia Gandhi runs Congress",
"Sachin is a good batsman"
],
"apikey": "DyMe1gSNhvMV1I1b20a7KARYIwuQX5GAQ",
"num_of_results": 2
}
I have verified on jsonlint that this is a valid JSON.
However while sending the request it gives me below error:
ValueError: No JSON object could be decoded
Can anyone please help me sort this out!!
The JSON object that you are passing in POST request is encoded into the url.
JSON library cannot read the encoded data.So you need to decode the url first.
Decoding of url can be done using urlparse library in python.so you need something like this.
post_data=urlparse.parse_qsl(self.request.body)
According to your need of final format to read there are various methods in urlparse.check this
or
As specified in the docs you can override a method to enable JSON parsing
def prepare(self):
if self.request.headers["Content-Type"].startswith("application/json"):
self.json_args = json.loads(self.request.body)
else:
self.json_args = None
check this