AWS Lambda Chalice: "The request could not be satisfied" Error - aws-lambda

I want my lambda function to return the response of another lambda function invoked via AWS API Gateway.
Both functions are deployed by Lambda Chalice to different APIs.
When the first function sends a request to the 2nd functions API endpoint, I am getting an error response saying that "The request could not be satisfied".
Any help is appreciated.
Edit to include some code as requested; shortened for brevity:
#app.route('/verify_user_token', methods=['GET'], cors=True)
def verify_user_token():
request = app.current_request
params = request.query_params or {}
# do your things here; if all goes well:
r = requests.get(ANOTHER_AWS_API_GATEWAY_ENDPOINT_URL, data=params)
return r.text

Related

Return status code when maximum retries attempted using backoff

Using asyncio and aiohttp, I have implemented an async function that triggers an API get request whenever a new record is inserted into database. If the request is successful, the status code has to be updated in database, otherwise the request should be retried 4 times and if it still fails, then the status code has to be updated in database.
To raise the exception on 404 status code, I have added raise_for_status flag to the aiohttp client session. When exception arises, the backoff decorator will retry the API call 4 times and when it still fails, it doesn't return any status code. This is what I have done:
# backoff decorator to retry failed API calls by "max_tries"
#backoff.on_exception(backoff.expo, aiohttp.ClientResponseError, max_tries=4, logger=logger)
async def call_url(language: str, word:str, headers:dict) -> bytes:
url = f"https://od-api.oxforddictionaries.com:443/api/v2/entries/{language}/{word.lower()}"
print(f"Started: {url}")
# Create aiohttp session to trigger 'get' dictionary API call with app_id, app_key as headers
async with aiohttp.ClientSession(headers=headers) as session:
# raise_for_status is used to raise exception for status_codes other than 200
async with session.get(url, raise_for_status=True) as response:
# Awaits response from dictionary API
content = await response.read()
status = response.status
print("Finished: ", status)
# Returns API status code to be updated in db
return status
I can't add the try-except clause because once exception is raised, it's handled by the try-except clause and the backoff doesn't retry the failed API call. Is there a way to make backoff decorator return the status code after maximum retries are attempted?
You say that "when it still fails it doesn't return any status code." But it has to either return something or else raise an exception. How about wrapping the call_url and handling the error situation in the wrapper function? The wrapper function always returns a status code. For instance:
async def my_call_url(language: str, word:str, headers:dict) -> bytes:
try:
return await call_url(language, word, headers)
except WhateverExceptionAiohttpRaises:
return some_status_code
If, instead of raising, the decorator returns None, you can make the appropriate changes.
Your code will now call this new function instead of the other one.

Get API Gateway's IP address in Lambda Function (by Python)

I have a Lambda function that has an API Gateway trigger and wonder if there are any method to get the API's IP address?
I already get the request Address by event & context like 'xxxxxxx.execute-api.ap-xxxx-1.amazonaws.com'. by following code:
import json
def lambda_handler(event, context):
result = str(event.get('params').get('header').get('Host'))
return result
the requester's ip is here:
event['requestContext']['identity']['sourceIp']

AWS Lambda Not Getting Query Parameters

I am setting up my first Lambda function on AWS. I use Python 3.6. My code is as follows:
def lambda_handler(event, context):
result = {}
result["Log stream name:"] = context.log_stream_name
result["Log group name:"] = context.log_group_name
result["Request ID:"] = context.aws_request_id
result["Mem. limits(MB)"] = context.memory_limit_in_mb
result["size of event"] = len(event)
result["type of event"] = str(type(event))
return result
I also set up an API Gateway for test Lambda.
However, no matter what query paramters I pass in to the API Gateway, the event is always an empty dict. Below is a sample response. What am I missing?
Request: /test/number?input=5
Status: 200
Latency: 223 ms
Response Body
{
"Log stream name:": "2018/12/05/[$LATEST]9d9fd5dd157046b4a67792aa49f5d71c",
"Log group name:": "/aws/lambda/test",
"Request ID:": "dce7beaf-f8c9-11e8-9cc4-85afb50a0e0c",
"Mem. limits(MB)": "128",
"size of event": 0,
"type of event": "<class 'dict'>"
}
Assuming you don't have request mapping templates, you should turn Lambda Proxy integration on.

Parsing the response using REST vs. SOAP API in Ruby

I am trying to parse a response that I receive using Rest API calls, but get an error when I say, something like: response.body.first[1]. I am transferring Soap API calls to rest API calls. Is response.first something that can only be used in Soap, if so what is the equivalent in Rest? Here is the code snippet that I am having trouble with:
url = ##rest_base_url.to_s + "filters/#{id.to_s}/results"
resource = RestClient::Resource.new url, #username, #password
response = resource.get
data = JSON.parse(response.body)["data"]
if response.body.first[1][:return].nil?
requirements = nil
elsif response.body.first[1][:return].is_a?(Array)
# puts "|get_requirements| req is an array".blue
requirements = []
Thank you

(REDDIT) Error trying to subscribe to subreddits via API

I know that Snoo seems to be unmaintained, but I wanted to use a ruby framework since I'm trying to improve my Ruby skill.
I'm trying to add some functionality starting with subscribing and unsubscribing to subreddits. Link to API doc.
My first attempt was with the built-in post method which returned a 404 error
def subscribe(subreddit)
logged_in?
post('/api/subscribe.json',body:{uh: #modhash, action:'sub', sr: subreddit, api_type: 'json'})
end
Since the built-in post method was giving me a 404 I decided to try the HTTParty post method:
def subscribe(subreddit)
logged_in?
HTTParty.post('http://www.reddit.com/api/subscribe.json',body:{uh: #modhash, action:'sub', sr: subreddit, api_type: 'json'})
end
That returns this:
pry(main)> reddit.subscribe('/r/nba')
=> {"json"=>{"errors"=>[["USER_REQUIRED", "please login to do that", nil]]}}
Does anyone know if I need to pass more info in the body or if I'm just sending a badly formed request? Thanks!
Also, before running "reddit.subscribe" I have verified that I'm logged in with with a cookie, a modhash, can access my account info, etc.
Solution found:
def subscribe(subreddit)
#query the subreddit for it's 'about' info and get json back
subreddit_json = self.subreddit_info(subreddit)
#build the coded unique identifier for the targeted subreddit
subreddit_id = subreddit_json['kind'] + "_" + subreddit_json['data']['id']
#send post request to server
server_response = self.class.post('/api/subscribe.json',
body:{uh:#modhash, action:'sub', sr: subreddit_id, api_type:'json'})
end
The Reddit API doesn't accept the subreddit name as the value passed with 'sr', (e.g. sr:'/r/funny'). It requires the subreddit "type" (which is always 't5' for subreddits) and unique forum id. The parameter passed would look something like: sr: "t5_2qo4s". This information is available if you go to your target subreddit and add about.json, e.g., www.reddit.com/r/funny/about.json

Resources