iT邦幫忙

第 11 屆 iThome 鐵人賽

DAY 6
0
Software Development

從Java進入AWS部署RESTful API的心路歷程系列 第 6

Day06-概觀(二)Run as API Gateway

  • 分享至 

  • xImage
  •  

我們大致上試過在AWS上建立API Gateway,並發出request讓Lambda產生回應了,但是上次的HelloLambda無法處理經過Proxy integration的request/response。這次我們來嘗試透過在SAM Local上運行API Gateway模式,進一步了解request/response的處理方式。

Run as API Gateway

首先,調整之前Run Configurations中設定的AWS SAM Local->LambdaExample SAM Local,將Run as:模式改選為API Gateway
https://ithelp.ithome.com.tw/upload/images/20190917/20120911tCO0C90738.png

下面的SAMlocal Coommand Configuration預設值,這將是我們本機測試運行的Host/Port

而再次執行LambdaExample SAM Local,編譯完成後將會在Console中啟動SAM Local並輸出內容,保持仍在運行的狀態

Mounting HelloLambda at http://127.0.0.1:3000/hello [DELETE, GET, HEAD, OPTIONS, PATCH, POST, PUT]
You can now browse to the above endpoints to invoke your functions. You do not need to restart/reload SAM CLI while working on your functions, changes will be reflected instantly/automatically. You only need to restart SAM CLI if you update your AWS SAM template
2019-09-17 15:12:19  * Running on http://127.0.0.1:3000/ (Press CTRL+C to quit)

會看到SAM Local按照 template.yaml當中的設定,將HelloLambda(template設定的名稱)掛載在http://127.0.0.1:3000/hello 的所有方法上。(使用ANY並不是好作法,但是我們之後再調整)
另外也有一段說明,你並不需要每次都restart/reload SAM Local,這是因為SAM Local直到request觸發event,SAM Local透過Docker invoke Lambda的時候每次都會重新載入程式(jar)。所以你只有第一次啟動SAM Local或修改template.yaml 的時候會需要再次執行Run as AWS SAM Local,而只是變更Java code的時候只要重新進行Maven package即可,所以也在Run as中新增一個Maven build吧。

當然,如果是需要重新啟動SAM Local,請記得將中止原本的SAM Local console,否則會因為port已經被佔用而啟動失敗喔。
你也可以在專案目錄下執行CLI以預設值啟動SAM Local

$ sam local start-api

Requst & Response

現在可以使用SAM Local測試API了
隨意發出一個request,這次就可以不用在header提供x-api-key
https://ithelp.ithome.com.tw/upload/images/20190917/201209112YWwchCwjP.png

當然,因為 response格式還是錯的,我們得到了http 502
但是SAM Local當中可以看到HelloLambda log輸出的request 內容

{ 
   httpMethod=POST,
   body=   { 
      "key1":"value1"
   },
   resource=/hello,
   requestContext=   { 
      resourceId=123456,
      apiId=1234567890,
      resourcePath=/hello,
      httpMethod=POST,
      requestId=c6af9ac6-7b61-11e6-9a41-93e8deadbeef,
      accountId=123456789012,
      stage=Prod,
      identity=      { 
         apiKey=null,
         userArn=null,
         cognitoAuthenticationType=null,
         caller=null,
         userAgent=Custom User Agent String,
         user=null,
         cognitoIdentityPoolId=null,
         cognitoAuthenticationProvider=null,
         sourceIp=127.0.0.1,
         accountId=null
      },
      extendedRequestId=null,
      path=/hello
   },
   queryStringParameters=null,
   multiValueQueryStringParameters=null,
   headers=   { 
      Cache-Control=no-cache,
      Postman-Token=4d185495-a813-47de-8631-c2bcfd27d30c,
      Content-Type=text/plain,
      User-Agent=PostmanRuntime/7.6.0,
      Accept=*/*,
      Host=localhost:3000,
      Accept-Encoding=gzip,
      deflate,
      Content-Length=17,
      Connection=keep-alive,
      X-Forwarded-Proto=http,
      X-Forwarded-Port=3000
   },
   multiValueHeaders=   { 
      Cache-Control=      [ 
         no-cache
      ],
      Postman-Token=      [ 
         4         d185495-a813-47de-8631-c2bcfd27d30c
      ],
      Content-Type=      [ 
         text/plain
      ],
      User-Agent=      [ 
         PostmanRuntime/7.6.0
      ],
      Accept=      [ 
         */*
      ],
      Host=      [ 
         localhost:3000
      ],
      Accept-Encoding=      [ 
         gzip,
         deflate
      ],
      Content-Length=      [ 
         17
      ],
      Connection=      [ 
         keep-alive
      ],
      X-Forwarded-Proto=      [ 
         http
      ],
      X-Forwarded-Port=      [ 
         3000
      ]
   },
   pathParameters=null,
   stageVariables=null,
   path=/hello,
   isBase64Encoded=false
}

Lambda Proxy integration轉換好所有的http request細節資料也增加了一些東西在裡面,而body中也有收到的json

但是我們想要先能正常運行,所以想先處理response的問題
按照接下來的log紀錄

Function returned an invalid response (must include one of: body, headers, multiValueHeaders or statusCode in the response object). Response received: "Hello from Lambda!"

原來是回傳的內容至少要包含body, headers, multiValueHeaders or statusCode之其一在response object。
那麼首先,我們需要將handleRequest return type以及implements RequestHandler都改為Object(記得將專案中的test code一起修改或拿掉,否則會編譯錯誤)。然後先改成用簡單的Anonymous class回傳代替

public class LambdaFunctionHandler implements RequestHandler<Object, Object> {

    @Override
    public Object handleRequest(Object input, Context context) {
        context.getLogger().log("Input: " + input);
        // TODO: implement your handler
        return new Object() {
            public int statusCode = 200;
            public String body = "Hello from Lambda!";
        };
    }
}

這時候我們再次送出request就能正確response了
https://ithelp.ithome.com.tw/upload/images/20190917/20120911h0vQiPK73v.png

只不過因為預設在response自動產生的Content-Type: application/json這個header,而目前的body並未符合json 格式,postman還表示不美麗呢...
明天再來試試看讀取request中的內容並且產生response好了...


上一篇
Day05-概觀(一)Lambda、API Gateway以及Lambda Proxy integration
下一篇
Day07-概觀(三)Json from Request
系列文
從Java進入AWS部署RESTful API的心路歷程30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言