How to filter an REST Result by sending custom request header parameter - endpoint

i have an ASP.NET Core 1.1 WebApi Endpoint like this one:
[ApiVersion("1.0")]
[Route("api/[controller]")]
public class SampleController : Controller
{
[HttpGet]
public IActionResult Get()
{
...
}
}
It returns a collection of 'Sample'-Objects to the caller.
Now i do like to send within the Request Header a Custom Attribute like 'App-Type' which let the Endpoint know which App asks for Data. But what is to do that the endpoint fetches this Attribute so that i have it as variable within the function?

If you want a parameter in a controller action that reads from the headers, you should use [FromHeader] attribute, in your case it will be like [FromHeader(Name="Accept-Language")]. More information in https://learn.microsoft.com/en-us/aspnet/core/mvc/models/model-binding

Related

How do I map path parameters from an API Gateway API to the Request Object of a Java Lambda

I have a lambda, written in Java, that accepts a Request Object of the structure
{
"id": "be1c320a-144f-464d-b32c-38ec7fb4445b",
"userId": "foobar"
}
When I call this Lambda through the test interface with such an object, it works fine.
I want to create an API where a GET request to
/users/foobar/items/be1c320a-144f-464d-b32c-38ec7fb4445b
i.e. of the form
/users/{userId}/items/{id}
calls this Lambda.
I have created the API resources /users, {userId}, items, and {id} appropriately.
And I have created the GET method (on /users/{userId}/items/{id})and associated it to the lambda.
When I test the API, it invokes the lambda, but with null values in the request. I can see it package the path as {"id":"be1c320a-144f-464d-b32c-38ec7fb4445b","userId": "foobar"} in the logs, but that's not being sent in the body.
I have tried creating a template map (and have tried RTFM), but cannot see how to map path parameters to a body.
How do I achieve this mapping?
I think your Request Object structure may not be properly configured. There may be a few ways to configure this. Here is some information that has helped me.
How to pass a querystring or route parameter to AWS Lambda from Amazon API Gateway - Demonstrates this mapping (albeit with python). However, taking the top response, if you enable "Use Lambda Proxy integration", you can similarily do this with Java as so:
#Override
public Object handleRequest(APIGatewayProxyRequestEvent input, Context context) {
Map<String, String> pathParameters = input.getPathParameters();
String id = pathParameters.get("id");
String userId = pathParameters.get("userId");
// Handle rest of request..
}
This is a tuturial using the serverless framework to create an Api with Java. This tutorial similarily accesses the pathParameters by parsing the input rather than using the APIGatewayProxyRequestEvent java class.
#Override
public Object handleRequest(Map<String, Object> input, Context context) {
try {
// get the 'pathParameters' from input
Map<String,String> pathParameters = (Map<String,String>)input.get("pathParameters");
String id = pathParameters.get("id");
String userId = pathParameters.get("userId");
} catch (Exception ex) {
logger.error("Error in retrieving product: " + ex);
}
}
Use a mapping template.
First, in the Method Request section, you should see userId and id as Request Paths
Then, in the Integration Request, do not choose Proxy Integration.
Then in the Mapping Templates section, add a new mapping template for application/json of the form
{
"id" : "$method.request.path.id",
"userId" : "$method.request.path.user_id"
}

How to map querystring and header to AWS C# lambda function parameter

I have AWS Gateway REST API that takes 2 querystring parameters
https://xxxxxx.xxxx.us-east-1.amazonaws.com/dev/pets?type=dog&page=1
The caller of the API also include x-api-key in the header. I want API gateway to pass querystring parameters and x-api-key to lambda function. So in AWS API Gateway Console i have configured the Integration Request as below
The lambda function looks like this
namespace AWSLambda1
{
public class Function
{
public string FunctionHandler(LambdaRequest request, ILambdaContext context)
{
return string.Format("{0},{1},{2}", request.Type, request.Page, request.ApiKey);
}
}
}
public class LambdaRequest
{
public string Type { get; set; }
public string Page { get; set; }
public string ApiKey { get; set; }
}
Issues
1> When lambda function receives the request, the Type and Page properties are coming as NULL.
2>As per documentation API Gateway can map the http header using the naming convention method.request.header.{param_name}, however when i try to set map from as method.request.header.x-api-key it throws error
Invalid mapping expression specified: Validation Result: warnings :
[], errors : [Invalid mapping expression parameter specified:
method.request.header.x-api-key]
I am not sure how do i map these query string and header to C# lambda object
(Please note that i have already gone through SO post that suggest to JObject as parameter for lambda function. But it only works for me if i enable Use Lambda Proxy integration in Integration Request. In such case API gateway pass all the information to lambda. This might work for me but i am trying to avoid passing unwanted information to lambda function)
Adding Full answer here.
Header Issue
First thing, you need to make sure header entry is added in Method Request and then you can go map that in Integration Request with mapping method.request.header.x-api-key. The error is happening because you did not add in Method Request section but trying to configure it in Integration Request only.
Lambda Payload Issue
It looks like you are not using Lambda Proxy Integration. If you use Lambda Proxy Integration then you will get full event JSON object event data to Lambda. Similar to answer given in post you have shared. This JSON object will contains headers, queryparameters, path variables, url, request body etc.,. If you want to see some sample on how it looks, just go and create API Gateway Test Event on Lambda.
Now, if you do not want to use Lambda Proxy Integration but want to limit what is being sent to Lambda then you will have to create Integration Mapping Template to send only required info to Lambda such as headers, payload, query params etc., from API Gateway.
Sample Integration Template.
{
"body" : $input.json('$'),
"headers": {
#foreach($header in $input.params().header.keySet())
"$header": "$util.escapeJavaScript($input.params().header.get($header))" #if($foreach.hasNext),#end
#end
},
"method": "$context.httpMethod",
"params": {
#foreach($param in $input.params().path.keySet())
"$param": "$util.escapeJavaScript($input.params().path.get($param))" #if($foreach.hasNext),#end
#end
},
"query": {
#foreach($queryParam in $input.params().querystring.keySet())
"$queryParam": "$util.escapeJavaScript($input.params().querystring.get($queryParam))" #if($foreach.hasNext),#end
#end
}
}
Reference -
https://kennbrodhagen.net/2015/12/06/how-to-create-a-request-object-for-your-lambda-event-from-api-gateway/
https://docs.aws.amazon.com/apigateway/latest/developerguide/api-gateway-mapping-template-reference.html

ServiceStack: Authenticate each request using headers in the HTTP request

I have have read other posts on the same topic, but I haven't really gotten a clear picture of how to best solve this:
I have a webservice, that is "stateless" when it comes to the authentication/session, meaning that the client will send two strings with every request (in the HTTP header), AuthToken and DeviceUUID.
These two strings are then compared to the storage, and if found, we know which user it is.
1)
Id like to use the [Authenticate] attribute for each service that I want to protect, and then a method should be executed where I check the two strings.
2)
If I add the [RequiredRole], a method should also be executed, where I have access to the HTTP headers (the two strings), so I can do my lookup.
I am unsure of how to do this in the easiest and cleanest manner possible. I do not want to create ServiceStack Session objects etc, I just want a method that, for each decorated services, runs a method to check authenticated state.
If you want to execute something else in addition when the [Authenticate] and [RequiredRole] attributes are used then it sounds like you want a custom [MyAuthenticate] Request Filter attribute which does both, i.e. validates that the request is Authenticated and executes your custom functionality, e.g:
public class MyAuthenticateAttribute : AuthenticateAttribute
{
public override async Task ExecuteAsync(IRequest req, IResponse res, object dto)
{
await base.ExecuteAsync(req, res, requestDto);
var authenticated = !res.IsClosed;
if (authenticated)
{
//...
}
}
}
Then use it instead of [Authenticate] in places where you need that extra functionality:
[MyAuthenticate]
public class MyServices { ... }
But I'd personally keep the logic in the attributes separated:
public class MyLogicPostAuthAttribute : RequestFilterAsyncAttribute
{
public override async Task ExecuteAsync(IRequest req, IResponse res, object dto)
{
//...
}
}
So they're explicit and can be layered independently of the [Authenticate] attribute, e.g:
[Authenticate]
[MyLogicPostAuth]
public class MyServices { ... }
Which can also be combined like:
[Authenticate, MyLogicPostAuth]
public class MyServices { ... }

Get public events from Facebook Graph API via Android SDK

I'm trying to get public events from Facebook Graph API with the following code:
val request = GraphRequest.newGraphPathRequest(
AccessToken.getCurrentAccessToken(),
"/search",
GraphRequest.Callback { response : GraphResponse ->
Log.e("E", response.toString())
}
)
val parameters = Bundle()
parameters.putString("q", "Toronto")
parameters.putString("fields", "city,state,country,description,id,start_time,end_time,name,place,street,zip")
parameters.putString("type", "event")
parameters.putString("limit", "25000")
request.parameteans = parameters
request.executeAsync()
But I'm getting an empty data array. When I change the "type" field from "event" to "place" then I actually get the data.
Why am I getting no data for the event?
https://developers.facebook.com/docs/graph-api/changelog/breaking-changes#search-4-4
You can no longer use the /search endpoint with the following object
types:
event
group
page
user

RESTFUL Web Service - List

I have a client application requesting a list of channels from a webservice. Is it possible to take the "response" from the web service and store it in an ArrayList?
Meaning if I wanted to store a list of channels for example, it would normally come from the web service as a response, typically from ResponseBuilder.
And I want to store it in an ArrayList from the client, like List.
How would I go about doing that?
You can use TypeReference to instantiate your Channel object list, here is an example:
import com.fasterxml.jackson.core.type.TypeReference;
public class ChannelClient {
public void getChannels() {
Response serviceResponse = client.target("http://your_service_url/channels/").
request(MediaType.APPLICATION_JSON).get(Response.class);
String responseString = serviceResponse.readEntity(String.class);
List<Channel> list = new ObjectMapper().readerFor(new TypeReference<List<Channel>>() {
}).readValue(responseString);
}
}
Make sure to have Jersey JSON Jackson jar in your dependencies, you can get it from here
https://mvnrepository.com/artifact/org.glassfish.jersey.media/jersey-media-json-jackson/2.26-b07
EDIT: In case you want to consume MediaType.TEXT_PLAIN response, you will just change the request method argument to your specified type like this:
Response serviceResponse = client.target("http://your_service_url/channels/").
request(MediaType.TEXT_PLAIN).get(Response.class);