3

I want to make an HTTP GET request to AGOL, but I want to route the request through a Python function.

Since I can't host the Python function on AGOL (more info here), I'd like to use AWS-Lambda instead.

HTTP GET requestAWS Lambda Python functionAGOL

What would it take to configure AWS Lambda so that it can serve as a middle tier between the HTTP GET request and AGOL?

asked Aug 9, 2020 at 2:07

2 Answers 2

4

Here's a sample AWS Lambda setup from a colleague:

  1. Create an AWS account (free).
  2. In AWS Lambda, create a new function.
    • Enter a function name and RuntimePython 3.7
  3. Write the function.
    • This sample script receives an ASSET_ID value from a URL, processes it with Python, and sends additional requests to AGOL. It returns a JSON dictionary.

from urllib.parse import urlencode
from urllib.request import Request, urlopen
import json
# Get a security token to append to all requests
def GetToken():
 username = '<my username>'
 password = '<my password>'
 url = 'https://www.arcgis.com/sharing/rest/generateToken' 
 post_fields = {'username': username,'password':password,'expiration':'60','client':'referer','referer':'http://www.arcgis.com','f':'json' }
 request = Request(url, urlencode(post_fields).encode())
 out = urlopen(request).read().decode()
 resp_dict = json.loads(out)
 # print (resp_dict['token'])
 return resp_dict['token']
# Query a feature service with a where clause returning all fields. Function returns a json dictionary
def queryFeatureService(url,token,where):
 post_fields = {'token': token,'where':where,'outfields':'*','returngeometry':'false','f':'json' }
 request = Request(url, urlencode(post_fields).encode())
 out = urlopen(request).read().decode()
 resp_dict = json.loads(out)
 return resp_dict
# Get the zone value from the matching Active Transportation feature 
def GetZone(jsonFeatures,zoneField):
 for feature in jsonFeatures['features']:
 # print (feature['attributes']['ZONE_'])
 return feature['attributes'][zoneField]
# Query with ASSET_ID, returning the workorder record with a new "ZONE_" field added from the matching Transportation layer
# 'lambda_handler' is the main function for Lambda. Code starts here when called
def lambda_handler(event, context):
 urlWorkorders = 'https://services.arcgis.com/Akv3yjcvcvmR0q1R/ArcGIS/rest/services/<my AGOL account name>/FeatureServer/0/query' 
 urlActiveTransportationPoints = 'https://services.arcgis.com/Akv3yjcvcvmR0q1R/ArcGIS/rest/services/Active_Transportation_Points/FeatureServer/0/query'
 token = GetToken() 
 ASSET_ID = event["queryStringParameters"]['asset_id']
 
 jsonWorkorder = queryFeatureService(urlWorkorders, token,"ASSET_ID = '" + ASSET_ID + "'")
 # JSON for the new "ZONE_" field, appends to return Workorder JSON object to give it this missing field
 fldZone = {'name':'ZONE_','type':'esriFieldTypeString','alias':'ZONE_','sqlType':'sqlTypeOther','length':15,'domain':None,'defaultValue':None}
 jsonWorkorder['fields'].append(fldZone)
 # Query the Active Transportation points with the same ASSET_ID
 jsonActiveTransportation = queryFeatureService(urlActiveTransportationPoints,token,"ASSET_ID = '" + ASSET_ID + "'")
 # Get the ZONE_ value
 zone = GetZone(jsonActiveTransportation,'ZONE_')
 # Set the ZONE_ value in the ZONE_ field that was added to workorders
 jsonWorkorder['features'][0]['attributes']['ZONE_'] = zone
 # return (jsonWorkorder)
 return {
 'statusCode': 200,
 'headers': {
 'Access-Control-Allow-Origin' : '*',
 'Access-Control-Allow-Headers' : '*'
 
 },
 'body': json.dumps(jsonWorkorder)
 }

  1. Choose Add TriggerAPI Gateway
  2. Choose Create a new API, REST API, SecurityOpen
  3. Open API Gateway: workorder-API hyperlink
  4. ActionsCreate methodGET ➔ configure as follows:
  5. Click Method Request header link ➔ expand Query String Parameters
  6. Add query string "asset_id"

Conclusion:

It's a pretty interesting solution that could be useful for people who have similar requirements.


A note about security:

The AWS Lambda function specifies/stores the AGOL username and password. This freaked me out at first.

However, since the username and password are server-side, they are never exposed to the client user.

  • In theory, we could write this same function as an AJAX call in JavaScript, but we would need to embed the credentials in the web code, making it unsecure, so that's why a server-side function is needed.

  • Additionally, we could alter the Lambda function to pass an AGOL-registered app's clientID and Secret for more granular access control—which would not have my username and password embedded in the function.

  • More info here: ArcGIS Web AppBuilder (Developer Edition). See the "Provide an app ID for Web AppBuilder" section (not just limited to just WAB, but for any app that needs a ClientID and Secret).

answered Aug 9, 2020 at 2:07
0

Thanks for your answer above but do you need to install any specific libraries or other tools to get it to run in AWS?

answered Jan 4, 2021 at 1:17
1
  • I got help from a developer I know. So he'd have to answer that question. Commented Jan 4, 2021 at 1:20

Your Answer

Draft saved
Draft discarded

Sign up or log in

Sign up using Google
Sign up using Email and Password

Post as a guest

Required, but never shown

Post as a guest

Required, but never shown

By clicking "Post Your Answer", you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.