Skip to content

Commit

Permalink
Add ability to send back headers
Browse files Browse the repository at this point in the history
Change Response debug to include whole response

Fix #133
Bug: 78534257
Bug: 78534258

Change-Id: I6deb87e533b39eb3a7679586c231878695b25b91
  • Loading branch information
Canain committed May 7, 2018
1 parent ba8d5cf commit 7efa485
Show file tree
Hide file tree
Showing 9 changed files with 137 additions and 14 deletions.
36 changes: 36 additions & 0 deletions src/_test/assistant.test.ts
Expand Up @@ -218,3 +218,39 @@ test('app is callable as an Express request', async t => {
},
})
})

test('app.handler can process requests and response with response headers', async t => {
const expectedHeaders = {
headers3: 'headers4',
}
const app = attach({
handler: async (body: JsonObject, headers: Headers): Promise<StandardResponse> => {
return {
body: {
},
status: 123,
headers: expectedHeaders,
}
},
})
t.is(typeof app.handler, 'function')
const res = await app.handler({}, {})
t.is(res.status, 123)
t.is(res.headers!.headers3, expectedHeaders.headers3)
})

test('app.handler adds content-type headers', async t => {
const app = attach({
handler: async (body: JsonObject, headers: Headers): Promise<StandardResponse> => {
return {
body: {
},
status: 123,
}
},
})
t.is(typeof app.handler, 'function')
const res = await app.handler({}, {})
t.is(res.status, 123)
t.is(res.headers!['content-type'], 'application/json; charset=utf-8')
})
19 changes: 11 additions & 8 deletions src/assistant.ts
Expand Up @@ -15,7 +15,7 @@
*/

import { OmniHandler, StandardHandler, BuiltinFrameworks, builtin } from './framework'
import { debug, values, stringify, info } from './common'
import * as common from './common'

/** @public */
export type AppHandler = OmniHandler & BaseApp
Expand Down Expand Up @@ -70,22 +70,25 @@ export const attach = <TService>(
let app: (BaseApp & TService) | (AppHandler & TService) = Object.assign(create(options), service)
// tslint:disable-next-line:no-any automatically detect any inputs
const omni: OmniHandler = (...args: any[]) => {
for (const framework of values(app.frameworks)) {
for (const framework of common.values(app.frameworks)) {
if (framework.check(...args)) {
return framework.handle(app.handler)(...args)
}
}
return app.handler(args[0], args[1])
}
app = Object.assign(omni, app)
const handler = app.handler.bind(app)
const handler: typeof app.handler = app.handler.bind(app)
const standard: StandardHandler = async (body, headers) => {
const log = app.debug ? info : debug
log('Request', stringify(body))
log('Headers', stringify(headers))
const log = app.debug ? common.info : common.debug
log('Request', common.stringify(body))
log('Headers', common.stringify(headers))
const response = await handler(body, headers)
log('Response', stringify(response.body))
log('Status', response.status)
if (!response.headers) {
response.headers = {}
}
response.headers['content-type'] = 'application/json; charset=utf-8'
log('Response', common.stringify(response))
return response
}
app.handler = standard
Expand Down
40 changes: 39 additions & 1 deletion src/framework/_test/express.test.ts
Expand Up @@ -17,7 +17,7 @@
import ava, { RegisterContextual } from 'ava'
import { Express } from '../express'
import { JsonObject } from '../../common'
import { StandardResponse } from '..'
import { StandardResponse, Headers } from '../framework'

interface AvaContext {
express: Express
Expand Down Expand Up @@ -134,3 +134,41 @@ test('handles error', async t => {
t.deepEqual(receivedBody, expectedBody)
t.is(receivedStatus, expectedStatus)
})

test('handles valid headers fine', async t => {
const expectedHeaders = {
header1: 'header2',
}
const expectedStatus = 123
const receivedHeaders: Headers = {}
let receivedStatus = -1
let promise: Promise<StandardResponse> | null = null
t.context.express.handle((body, headers) => {
promise = Promise.resolve({
body: {},
status: expectedStatus,
headers: expectedHeaders,
})
return promise
})({
body: {},
headers: {},
get() {},
// tslint:disable-next-line:no-any mocking request
} as any, {
status(status: number) {
receivedStatus = status
return this
},
setHeader(key: string, value: string) {
receivedHeaders[key] = value
},
send() {
return this
},
// tslint:disable-next-line:no-any mocking response
} as any)
await promise
t.is(receivedStatus, expectedStatus)
t.deepEqual(receivedHeaders, expectedHeaders)
})
32 changes: 32 additions & 0 deletions src/framework/_test/lambda.test.ts
Expand Up @@ -155,3 +155,35 @@ test('handles error', async t => {
await new Promise(resolve => setTimeout(resolve))
t.is(receivedError, expectedError)
})

test('handles valid headers fine', async t => {
const expectedHeaders = {
header1: 'header2',
}
const expectedStatus = 123
let receivedHeaders: Headers | null = null
let receivedStatus = -1
let promise: Promise<StandardResponse> | null = null
t.context.lambda.handle((body, headers) => {
promise = Promise.resolve({
body: {},
status: expectedStatus,
headers: expectedHeaders,
})
return promise
})({
body: JSON.stringify({}),
headers: {},
}, {
succeed() {},
// tslint:disable-next-line:no-any mocking context
} as any, (e: Error, body: JsonObject) => {
receivedStatus = body.statusCode
receivedHeaders = body.headers
})
await promise
await new Promise(resolve => setTimeout(resolve))
// tslint:disable-next-line:no-any change to string even if null
t.is(receivedStatus, expectedStatus)
t.is(receivedHeaders, expectedHeaders)
})
13 changes: 10 additions & 3 deletions src/framework/express.ts
Expand Up @@ -20,7 +20,7 @@

import { Framework, StandardHandler } from './framework'
import { Request, Response } from 'express'
import { error } from '../common'
import * as common from '../common'

export interface ExpressHandler {
/** @public */
Expand All @@ -32,9 +32,16 @@ export class Express implements Framework<ExpressHandler> {
handle(standard: StandardHandler) {
return (request: Request, response: Response) => {
standard(request.body, request.headers)
.then(({ status, body }) => response.status(status).send(body))
.then(({ status, body, headers }) => {
if (headers) {
for (const key in headers) {
response.setHeader(key, headers[key]!)
}
}
response.status(status).send(body)
})
.catch((e: Error) => {
error(e.stack || e)
common.error(e.stack || e)
response.status(500).send({ error: e.message })
})
}
Expand Down
3 changes: 3 additions & 0 deletions src/framework/framework.ts
Expand Up @@ -67,6 +67,9 @@ export interface StandardResponse {

/** @public */
body: JsonObject

/** @public */
headers?: Headers
}

/** @public */
Expand Down
6 changes: 4 additions & 2 deletions src/framework/lambda.ts
Expand Up @@ -19,7 +19,8 @@
*/

import { Framework, StandardHandler, Headers } from './framework'
import { JsonObject, error } from '../common'
import { JsonObject } from '../common'
import * as common from '../common'
import { Context, Callback } from 'aws-lambda'

export interface LambdaHandler {
Expand All @@ -37,7 +38,7 @@ export class Lambda implements Framework<LambdaHandler> {
return o
}, {} as Headers)
const result = await standard(JSON.parse(event.body), headers).catch((e: Error) => {
error(e.stack || e)
common.error(e.stack || e)
callback(e)
})
if (!result) {
Expand All @@ -47,6 +48,7 @@ export class Lambda implements Framework<LambdaHandler> {
callback(null, {
statusCode: status,
body: JSON.stringify(body),
headers: result.headers,
})
}
}
Expand Down
1 change: 1 addition & 0 deletions src/service/actionssdk/actionssdk.ts
Expand Up @@ -337,6 +337,7 @@ export const actionssdk: ActionsSdk = <
}
return {
status: 200,
headers: {},
body: conv.serialize(),
}
},
Expand Down
1 change: 1 addition & 0 deletions src/service/dialogflow/dialogflow.ts
Expand Up @@ -412,6 +412,7 @@ export const dialogflow: Dialogflow = <
}
return {
status: 200,
headers: {},
body: conv.serialize(),
}
},
Expand Down

0 comments on commit 7efa485

Please sign in to comment.