I am trying to integrate AWS API Gateway with an AWS lambda function. The integration works flawlessly until I use the 'Lambda Proxy integration' in my Integration Request.
When I check 'Use Lambda Proxy integration' in my integration request, I start getting:
"Execution failed due to configuration error: Malformed Lambda proxy
response"
I googled around a bit and realized that I need to send back the response in a certain format:
{
"isBase64Encoded": true|false,
"statusCode": httpStatusCode,
"headers": { "headerName": "headerValue", ... },
"body": "..."
}
However, despite doing that, I still continue to see the same error. What am I doing wrong?
This is what my Lambda function looks like:
#Override
public String handleRequest(Object input, Context context) {
context.getLogger().log("Input: " + input);
return uploadN10KWebsiteRepositoryToS3();
}
private String uploadN10KWebsiteRepositoryToS3() {
/*BitbucketToS3Upload.JsonResponse jsonResponse = new BitbucketToS3Upload.JsonResponse();
jsonResponse.body = "n10k_website repository uploaded to S3...";
String jsonString = null;
try {
ObjectMapper mapper = new ObjectMapper();
jsonString = mapper.writeValueAsString(jsonResponse);
HashMap<String, Object> test = new HashMap<String, Object>();
test.put("statusCode", 200);
test.put("headers", null);
test.put("body", "n10k_website repository uploaded to S3");
test.put("isBase64Encoded", false);
jsonString = mapper.writeValueAsString(test);
}
catch (Exception e) {
int i = 0;
}*/
//return jsonString;
return "{\"isBase64Encoded\":false, \"statusCode\":200, \"headers\":null, \"body\": \"n10k_website repository uploaded to S3\"}";
}
When I test the API from API Gateway console, this is the response I get:
Received response. Integration latency: 4337 ms Mon Aug 07 00:33:45
UTC 2017 : Endpoint response body before transformations:
"{\"isBase64Encoded\":false, \"statusCode\":200, \"headers\":null,
\"body\": \"n10k_website repository uploaded to S3\"}"
Mon Aug 07 00:33:45 UTC 2017 : Endpoint response headers:
{x-amzn-Remapped-Content-Length=0,
x-amzn-RequestId=0ff74e9d-7b08-11e7-9234-a1a04edc223f,
Connection=keep-alive, Content-Length=121, Date=Mon, 07 Aug 2017
00:33:45 GMT,
X-Amzn-Trace-Id=root=1-5987b565-7a66a2fd5fe7a5ee14c22633;sampled=0,
Content-Type=application/json}
Mon Aug 07 00:33:45 UTC 2017 : Execution failed due to configuration
error: Malformed Lambda proxy response
Mon Aug 07 00:33:45 UTC 2017 : Method completed with status: 502
If I un-check the 'Use Lambda Proxy integration', everything works okay. But I want to know why my response is malformed and how to fix it. Thanks!
I figured it out. I was sending the response back in an incorrect manner.
The response had to be sent back as a POJO object directly rather than serializing the POJO and sending it back as a String. This is how I got it to work.
public class BitbucketToS3Upload implements RequestHandler<Object, JsonResponse> {
#Data
public static class JsonResponse {
boolean isBase64Encoded = false;
int statusCode = HttpStatus.SC_OK;
String headers = null;
String body = null;
}
#Override
public JsonResponse handleRequest(Object input, Context context) {
context.getLogger().log("Input: " + input);
return uploadN10KWebsiteRepositoryToS3();
}
private JsonResponse uploadN10KWebsiteRepositoryToS3() {
BitbucketToS3Upload.JsonResponse jsonResponse = new BitbucketToS3Upload.JsonResponse();
jsonResponse.body = "n10k_website repository uploaded to S3";
String jsonString = null;
try {
ObjectMapper mapper = new ObjectMapper();
jsonString = mapper.writeValueAsString(jsonResponse);
System.out.println(jsonString);
//jsonString = mapper.writeValueAsString(test);
}
catch (Exception e) {
int i = 0;
}
return jsonResponse;
//return "{\"isBase64Encoded\":false, \"statusCode\":200, \"headers\":null, \"body\": \"n10k_website repository uploaded to S3\"}";
}
}
Hope this helps someone!
Related
I've a lambda function that does some verification before inserting data into dynamoDB. I wish to return a 400 HttpStatus code if the passed payload is invalid and that's the reason I've googled and found
public async Task<APIGatewayProxyResponse> FunctionHandler(RequestItem request, ILambdaContext context)
{
But when I return the code as
private static APIGatewayProxyResponse GetBadRequestResponse()
{
var responseBadRequest = new APIGatewayProxyResponse
{
StatusCode = (int)HttpStatusCode.BadRequest,
Body = "Invalid payload sent",
// Headers = new Dictionary<string, string> { { "Content-Type", "text/plain" } }
};
return responseBadRequest;
}
It returns a 200 with the content of
{
"statusCode": 400,
"body": "Invalid payload sent",
"isBase64Encoded": false
}
In the AWS Console I did
But doing so If I put the APIGatewayProxyRequest as request, I've got null for Body field
Anyone has got a simila situation?
I need to download a image files from the file system using RESTEasy web service and the input httpclient is JSON and the output response is
#Produces({"image/jpeg,image/png"})
Here is my client code:
public void getFileDownload(){
log("inside getServerPath....");
DefaultHttpClient httpClient = new DefaultHttpClient();
HttpPost httpPost = new HttpPost(downloadWebService_URL);
JSONObject json = new JSONObject();
json.put("filePath", "/ngs/app/sample.png");
json.put("fileName", "sample.png");
log("json-->"+json.toString());
StringEntity inputJson = null;
try {
inputJson = new StringEntity(json.toString());
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
}
log("inputJson = " + inputJson.toString());
inputJson.setContentType("application/json");
httpPost.setEntity(inputJson);
httpPost.addHeader("AppType", "TC");
log("httpPost... httpPost");
HttpResponse response = null;
try {
response = httpClient.execute(httpPost);
log("response:-->"+response);
}
catch (ClientProtocolException e) {
e.printStackTrace();
}
catch (IOException e) {
e.printStackTrace();
}
catch (Exception e)
{
log("E:: " + ExceptionUtils.getStackTrace(e));
}
}
Here is my Webservice code:
#Path("/downloadservice")
public class DownloadFileWS {
private static final String FILE_PATH = "/ngs/app/sample.png";
#POST
// #Path("/images")
#Path("/{fileName}/images")
#Consumes({"application/json"})
#Produces({"image/jpeg,image/png"})
public Response getImageFile(#PathParam("fileName") String fileName) {
File file = new File(FILE_PATH);
System.out.println("File requested is : " + fileName);
Logger.getLogger("!!!!!!!!!!!"+FILE_PATH);
System.out.println("########"+FILE_PATH);
ResponseBuilder response = Response.ok((Object) file);
response.header("Content-Disposition","attachment; filename=\"sample.png\"");
return response.build();
}
The HTTP Response is:
response:-->HTTP/1.1 200 OK [Date: Tue, 19 Jul 2016 00:36:22 GMT,
Content-Length: 6192, Content-Type: image/png, Content-Disposition:
attachment; filename="sample.png", X-Powered-By: Servlet/2.5 JSP/2.1]
org.apache.http.conn.BasicManagedEntity#2ace1307
Question:
1. Based on the response, it looks like the service is sending the image in HTTPResponse object. May i know how to download the image received from HTTP Response?
2. The requirement is to click a link which calls the webservice by passing JSON as input request and the image should automatically download to the user's local machine browser.
Using POSTMAN, I'm struggling to to retrieve my Identity Server 3 token.
Error code is : 400 Bad Request
Here are the details:
POST /identity/connect/token HTTP/1.1
Host: localhost:44358
Content-Type: application;x-www-form-urlencoded
Cache-Control: no-cache
Postman-Token: 57fc7aef-0006-81b2-8bf8-8d46b77d21d1
username=MYUSER-ID&password=MY-PASSWORD&grant_type=password&client_id=rzrwebguiangulajsclient&client_secret=myclientsecret&redirect_uri=https://localhost:44331/callback
I've done something similar with a simple Visual Studio 2015 WebApi project, where the end point was \token.
Any guidance/advice is appreciated...
regards,
Bob
The minimum required for a Resource Owner OAuth request is the following (line breaks added for readability):
POST /connect/token
Header
Content-Type: application/x-www-form-urlencoded
Body
username=MYUSER-ID
&password=MY-PASSWORD
&grant_type=password
&client_id=rzrwebguiangulajsclient
&client_secret=myclientsecret
&scope=api
Off the bat you are not requesting a scope in your request. Otherwise there is most probably something wrong in the configuration of your client within Identity Server.
Your best bet would be to enable logging and look at what comes back when this request errors.
Update: also, please don't use the ROPC grant type
I'm happy to say that we got Postman to work.
It turns out I was so close to getting Postman to work with Identity Server 3 Authorization.
The final piece to the solution was setting the Postman client Flow to Flow = Flows.ClientCredentials (see the postmantestclient client definition below):
using System.Collections.Generic;
using IdentityServer3.Core.Models;
namespace MyWebApi.MyIdentityServer.Config
{
public static class Clients
{
public static IEnumerable<Client> Get()
{
return new[]
{
new Client
{
ClientId = MyConstants.MyIdentityServer.MyWebGuiClientId,
ClientName = "My Web Gui Client",
Flow = Flows.Implicit,
AllowAccessToAllScopes = true,
IdentityTokenLifetime = 300,
AccessTokenLifetime = 300, //5 minutes
RequireConsent = false,
// redirect = URI of the Angular application
RedirectUris = new List<string>
{
MyConstants.MyIdentityServer.MyWebGuiUri + "callback.html",
// for silent refresh
MyConstants.MyIdentityServer.MyWebGuiUri + "silentrefreshframe.html"
},
PostLogoutRedirectUris = new List<string>()
{
MyConstants.MyIdentityServer.MyWebGuiUri + "index.html"
}
},
new Client
{
ClientId = MyConstants.MyIdentityServer.SwaggerClientId,
ClientName = "Swagger Client",
Flow = Flows.Implicit,
AllowAccessToAllScopes = true,
IdentityTokenLifetime = 300,
AccessTokenLifetime = 300,
RequireConsent = false,
// redirect = URI of the Angular application
RedirectUris = new List<string>
{
"https://localhost:44358/swagger/ui/o2c-html"
}
},
new Client
{
ClientId = "postmantestclient",
ClientName = "Postman http test client",
Flow = Flows.ClientCredentials,
AllowAccessToAllScopes = true,
IdentityTokenLifetime = 300,
AccessTokenLifetime = 300, //5 minutes
RequireConsent = false,
ClientSecrets = new List<Secret>
{
new Secret("PostmanSecret".Sha256())
},
RedirectUris = new List<string>()
{
"https://www.getpostman.com/oauth2/callback"
}
}
};
}
}
}
I'm testing out web service handlers, and I've created two mock services and a mock client. The client (A) calls the service (B) which calls the other service (C). I have one handler on B and another on C, both just print that they have been activated. What I would expect is for the B handler to activate 4 times (once when A contacts him, once when he contacts C, once when C replies and once when B should reply to A), but he only activates when A contacts him and when he has to reply to A. The handler on C work as expected (is activated twice).
I have the following code that starts the services and activates the client:
Endpoint.publish("http://localhost:8080/WSSecurity/helloworld", new WSDocEndpointImpl());
Endpoint.publish("http://localhost:8081/WSSecurity2/helloworld2", new WSDocEndpointImpl2());
URL wsdlUrl = new URL("http://localhost:8081/WSSecurity2/helloworld2?wsdl");
QName qname = new QName("http://webservice2.document.ftn.uns.ac.rs/", "WSDocEndpointImpl2Service");
Service service = Service.create(wsdlUrl, qname);
WSDocEndpoint2 helloWS = service.getPort(WSDocEndpoint2.class);
String response = helloWS.getHelloWorldAsString("Petar");
System.out.println(response);
My web services:
#WebService(endpointInterface = "rs.ac.uns.ftn.document.webservice.WSDocEndpoint")
#HandlerChain(file = "/rs/ac/uns/ftn/document/handler-chain-document.xml")
public class WSDocEndpointImpl implements WSDocEndpoint {
#Override
public String getHelloWorldAsString(String name) {
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("ARRIVED AT WS 1 --- " + new Date());
return "Hello, " + name;
}
}
#WebService(endpointInterface = "rs.ac.uns.ftn.document.webservice2.WSDocEndpoint2")
#HandlerChain(file = "/rs/ac/uns/ftn/document/handler-chain-document2.xml")
public class WSDocEndpointImpl2 implements WSDocEndpoint2 {
#Override
public String getHelloWorldAsString(String name) {
try {
URL wsdlUrl = new URL(
"http://localhost:8080/WSSecurity/helloworld?wsdl");
QName qname = new QName(
"http://webservice.document.ftn.uns.ac.rs/",
"WSDocEndpointImplService");
Service service = Service.create(wsdlUrl, qname);
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("ARRIVED AT WS 2 --- " + new Date());
WSDocEndpoint helloWS = service.getPort(WSDocEndpoint.class);
String responseFromWS1 = helloWS.getHelloWorldAsString("Petar");
return responseFromWS1;
} catch (Exception e) {
return "EXCEPTION!";
}
}
}
The handle message methods:
#Override
public boolean handleMessage(SOAPMessageContext context) {
try {
Thread.sleep(2000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.err.println("TEST HANDLER! --- " + new Date());
return true;
}
And finally the xml:
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<hc:handler-chains xmlns:hc="http://java.sun.com/xml/ns/javaee" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<hc:handler-chain>
<hc:handler>
<hc:handler-class>rs.ac.uns.ftn.document.handler.TestHandler</hc:handler-class>
</hc:handler>
</hc:handler-chain>
</hc:handler-chains>
The output I get on the console:
TEST HANDLER 2! --- Fri May 15 18:58:35 CEST 2015
ARRIVED AT WS 2 --- Fri May 15 18:58:36 CEST 2015
TEST HANDLER! --- Fri May 15 18:58:38 CEST 2015
ARRIVED AT WS 1 --- Fri May 15 18:58:39 CEST 2015
TEST HANDLER! --- Fri May 15 18:58:41 CEST 2015
TEST HANDLER 2! --- Fri May 15 18:58:43 CEST 2015
Hello, Petar
The problem was in the way I wrote my code. When my web service acted as a client it wasn't processing the handler. I had to generate a web service client for my web service and register the handler on him, and then use him to call my other web service.
How can i respond back with a text file containing json data upon request from client .
The request url is:
http://localhost:8082/web/ws/datafileid/json/Sat May 16 12:05:07 IST 2015.txt/
Controller code that handles the request is:
#RequestMapping(value=EmpRestURIConstants.DATAFILE_REQUEST,method=RequestMethod.GET)
#ResponseBody
public String datafileresponse(#PathVariable("filename") String filename, HttpServletResponse response) {
return cinehomeRestService.checkfilevalid(filename);
}
Service class that handles the request to check the file exists is:
#Override
public String checkfilevalid(String filename) {
String datafilename=webServiceDao.getdatafilename();
JSONObject obj = new JSONObject();
if(datafilename.equals(filename)) {
return "file";
}
else {
try {
obj.put("status", "022");
} catch (JSONException e) {
e.printStackTrace();
}
return obj.toString();
}
}
Here I need to respond back with the datafile.txt that exists at location resources. How can I perform the task. Can anyone help?
i have tried a method
#RequestMapping(value=EmpRestURIConstants.DATAFILE_REQUEST,method=RequestMethod.GET,produces=MediaType.APPLICATION_JSON_VALUE)
public #ResponseBody Response datafileresponse(#PathVariable("filename")String filename) throws IOException{
JSONObject readdata = new JSONObject();
String uploadPath = servletContext.getRealPath("");
String fullyqualifiedfilename=uploadPath+filename;
System.out.println("+++++++++"+fullyqualifiedfilename);
return Response.ok(uploadPath)
.header("Content-Disposition", "attachment; filename=\"" + fullyqualifiedfilename + "\"" ) //optional
.build();
}
i GOT THE REPLY AS...
{ "statusType": "OK", "entity": /home/cine/WORKSPACES/study/.metadata/.plugins/org.eclipse.wst.server.core/tmp0/wtpwebapps/
"entityType": "java.lang.String", "metadata": { "Content-Disposition": [ "attachment;
filename="/home/cine/WORKSPACES/study/.metadata/.plugins/org.eclipse.wst.server.core/tmp0/wtpwebapps/Cine Sat May 16 12:05:07 IST 2015.txt"" ] }, "status": 200 }
What this status means. Does the client can fetch teh file using this response.??