Skip to content
Permalink
Browse files

add X-Context header field. Closes #657

add X-Context header field. Closes #657

add X-Context header field. Closes #657
  • Loading branch information...
tj committed May 11, 2018
1 parent f63a805 commit 7b607bf0cffa20b2916e3b5cd6056e68534337a7
Showing with 105 additions and 68 deletions.
  1. +40 −4 docs/07-guides.md
  2. +21 −21 internal/proxy/event.go
  3. +41 −43 internal/proxy/event_test.go
  4. +3 −0 internal/proxy/request.go
@@ -682,10 +682,46 @@ You may alter this command for `up start` with the development environment. For

Note that the server must always listen on `PORT` which is provided by `up start`.

## Pre-Warming Lambda's, Monitoring Performance & Uptime
## Accessing Lambda Context

AWS Lambda works by serving your app on-demand, only when it is receiving traffic. Upon the first request it has to fetch your app's zip from S3 and initialize, this is called a "cold start", which incurs some additional latency. After this the Lambda is considered "warm" while in use, which can last several hours even between requests.
Traditional AWS Lambda functions a provided a context object which contains runtime information such as API Gateway user identity. This information is exposed as JSON in the `X-Context` header field in Up as shown here:

To mitigate cold starts with "pre-warming" you can schedule requests to your app—one convenient way to do this is to use an uptime monitoring tool such as [Apex Ping](https://apex.sh/ping/) which also monitors performance, so it's a win-win! Use the "up" coupon for 15% off your first year if you choose to use Ping.
```js
const http = require('http')
const { PORT } = process.env
const app = http.createServer((req, res) => {
const ctx = JSON.parse(req.headers['x-context'])
res.end(JSON.stringify(ctx, null, 2))
})
console.log('Starting app on %s', PORT)
app.listen(PORT)
```

[![Uptime Monitoring Tool](https://apex-software.imgix.net/ping/marketing/overview.png?compress=auto)](https://apex.sh/ping)
Output will be similar to the following. Visit the [AWS Documentation](https://docs.aws.amazon.com/lambda/latest/dg/nodejs-prog-model-context.html) for details.

```json
{
"apiId": "g4yn392afg",
"resourceId": "ez0z8areob",
"requestId": "d8314ef1-5543-11e8-a925-21fa0dd01c37",
"accountId": "337344593553",
"stage": "staging",
"identity": {
"apiKey": "",
"accountId": "",
"userAgent": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_12_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/66.0.3359.139 Safari/537.36",
"sourceIp": "64.110.31.100",
"accessKey": "",
"caller": "",
"user": "",
"userARN": "",
"cognitoIdentityId": "",
"cognitoIdentityPoolId": "",
"cognitoAuthenticationType": "",
"cognitoAuthenticationProvider": ""
},
"authorizer": null
}
```
@@ -2,31 +2,31 @@ package proxy

// Identity is the identity information associated with the request.
type Identity struct {
APIKey string
AccountID string
UserAgent string
SourceIP string
AccessKey string
Caller string
User string
UserARN string
CognitoIdentityID string
CognitoIdentityPoolID string
CognitoAuthenticationType string
CognitoAuthenticationProvider string
APIKey string `json:"apiKey"`
AccountID string `json:"accountId"`
UserAgent string `json:"userAgent"`
SourceIP string `json:"sourceIp"`
AccessKey string `json:"accessKey"`
Caller string `json:"caller"`
User string `json:"user"`
UserARN string `json:"userARN"`
CognitoIdentityID string `json:"cognitoIdentityId"`
CognitoIdentityPoolID string `json:"cognitoIdentityPoolId"`
CognitoAuthenticationType string `json:"cognitoAuthenticationType"`
CognitoAuthenticationProvider string `json:"cognitoAuthenticationProvider"`
}

// RequestContext is the contextual information provided by API Gateway.
type RequestContext struct {
APIID string
ResourceID string
RequestID string
HTTPMethod string
ResourcePath string
AccountID string
Stage string
Identity Identity
Authorizer map[string]string `json:"-"`
APIID string `json:"apiId"`
ResourceID string `json:"resourceId"`
RequestID string `json:"requestId"`
HTTPMethod string `json:"-"`
ResourcePath string `json:"-"`
AccountID string `json:"accountId"`
Stage string `json:"stage"`
Identity Identity `json:"identity"`
Authorizer map[string]string `json:"authorizer"`
}

// Input is the input provided by API Gateway.
@@ -240,7 +240,7 @@ func ExampleInput_get() {
json.Unmarshal([]byte(getEvent), &in)
output(in)
// Output:
// {
// {
// "HTTPMethod": "GET",
// "Headers": {
// "Accept": "*/*",
@@ -273,27 +273,26 @@ func ExampleInput_get() {
// "env": "prod"
// },
// "RequestContext": {
// "APIID": "iwcgwgigca",
// "ResourceID": "jcl9w3",
// "RequestID": "344b184b-5cfc-11e7-8483-27dbb2d30a77",
// "HTTPMethod": "GET",
// "ResourcePath": "/{proxy+}",
// "AccountID": "111111111",
// "Stage": "prod",
// "Identity": {
// "APIKey": "",
// "AccountID": "",
// "UserAgent": "curl/7.48.0",
// "SourceIP": "207.102.57.26",
// "AccessKey": "",
// "Caller": "",
// "User": "",
// "UserARN": "",
// "CognitoIdentityID": "",
// "CognitoIdentityPoolID": "",
// "CognitoAuthenticationType": "",
// "CognitoAuthenticationProvider": ""
// }
// "apiId": "iwcgwgigca",
// "resourceId": "jcl9w3",
// "requestId": "344b184b-5cfc-11e7-8483-27dbb2d30a77",
// "accountId": "111111111",
// "stage": "prod",
// "identity": {
// "apiKey": "",
// "accountId": "",
// "userAgent": "curl/7.48.0",
// "sourceIp": "207.102.57.26",
// "accessKey": "",
// "caller": "",
// "user": "",
// "userARN": "",
// "cognitoIdentityId": "",
// "cognitoIdentityPoolId": "",
// "cognitoAuthenticationType": "",
// "cognitoAuthenticationProvider": ""
// },
// "authorizer": null
// }
// }
}
@@ -333,27 +332,26 @@ func ExampleInput_post() {
// "IsBase64Encoded": false,
// "StageVariables": null,
// "RequestContext": {
// "APIID": "iwcgwgigca",
// "ResourceID": "jcl9w3",
// "RequestID": "50f6e0ce-5cfc-11e7-ada1-4f5cfe727f01",
// "HTTPMethod": "POST",
// "ResourcePath": "/{proxy+}",
// "AccountID": "111111111",
// "Stage": "prod",
// "Identity": {
// "APIKey": "",
// "AccountID": "",
// "UserAgent": "curl/7.48.0",
// "SourceIP": "207.102.57.26",
// "AccessKey": "",
// "Caller": "",
// "User": "",
// "UserARN": "",
// "CognitoIdentityID": "",
// "CognitoIdentityPoolID": "",
// "CognitoAuthenticationType": "",
// "CognitoAuthenticationProvider": ""
// }
// "apiId": "iwcgwgigca",
// "resourceId": "jcl9w3",
// "requestId": "50f6e0ce-5cfc-11e7-ada1-4f5cfe727f01",
// "accountId": "111111111",
// "stage": "prod",
// "identity": {
// "apiKey": "",
// "accountId": "",
// "userAgent": "curl/7.48.0",
// "sourceIp": "207.102.57.26",
// "accessKey": "",
// "caller": "",
// "user": "",
// "userARN": "",
// "cognitoIdentityId": "",
// "cognitoIdentityPoolId": "",
// "cognitoAuthenticationType": "",
// "cognitoAuthenticationProvider": ""
// },
// "authorizer": null
// }
// }
}
@@ -2,6 +2,7 @@ package proxy

import (
"encoding/base64"
"encoding/json"
"net/http"
"net/url"
"strconv"
@@ -55,6 +56,8 @@ func NewRequest(e *Input) (*http.Request, error) {
}

// custom fields
b, _ := json.Marshal(e.RequestContext)
req.Header.Set("X-Context", string(b))
req.Header.Set("X-Request-Id", e.RequestContext.RequestID)
req.Header.Set("X-Stage", e.RequestContext.Stage)

0 comments on commit 7b607bf

Please sign in to comment.
You can’t perform that action at this time.