Navigation Menu

Skip to content

Commit

Permalink
Merge pull request #1178 from grakic/no-strip-trailing-slash
Browse files Browse the repository at this point in the history
Add '--noStripTrailingSlashInUrl' option
  • Loading branch information
pgrzesik committed May 9, 2021
2 parents 0a5ded7 + e9695ec commit 4dbab1a
Show file tree
Hide file tree
Showing 8 changed files with 106 additions and 2 deletions.
1 change: 1 addition & 0 deletions README.md
Expand Up @@ -129,6 +129,7 @@ All CLI options are optional:
--layersDir The directory layers should be stored in. Default: ${codeDir}/.serverless-offline/layers'
--noAuth Turns off all authorizers
--noPrependStageInUrl Don't prepend http routes with the stage.
--noStripTrailingSlashInUrl Don't strip trailing slash from http routes.
--noTimeout -t Disables the timeout feature.
--prefix -p Adds a prefix to every path, to send your requests to http://localhost:3000/[prefix]/[your_path] instead. Default: ''
--printOutput Turns on logging of your lambda outputs in the terminal.
Expand Down
4 changes: 4 additions & 0 deletions src/config/commandOptions.js
Expand Up @@ -59,6 +59,10 @@ export default {
usage: "Don't prepend http routes with the stage.",
type: 'boolean',
},
noStripTrailingSlashInUrl: {
usage: "Don't strip trailing slash from http routes.",
type: 'boolean',
},
noAuth: {
usage: 'Turns off all authorizers',
type: 'boolean',
Expand Down
1 change: 1 addition & 0 deletions src/config/defaultOptions.js
Expand Up @@ -22,6 +22,7 @@ export default {
layersDir: null,
noAuth: false,
noPrependStageInUrl: false,
noStripTrailingSlashInUrl: false,
noTimeout: false,
prefix: '',
printOutput: false,
Expand Down
3 changes: 2 additions & 1 deletion src/events/http/HttpServer.js
Expand Up @@ -47,6 +47,7 @@ export default class HttpServer {
host,
httpPort,
httpsProtocol,
noStripTrailingSlashInUrl,
} = this.#options

const serverOptions = {
Expand All @@ -55,7 +56,7 @@ export default class HttpServer {
router: {
// allows for paths with trailing slashes to be the same as without
// e.g. : /my-path is the same as /my-path/
stripTrailingSlash: true,
stripTrailingSlash: !noStripTrailingSlashInUrl,
},
state: enforceSecureCookies
? {
Expand Down
6 changes: 5 additions & 1 deletion src/utils/generateHapiPath.js
Expand Up @@ -12,7 +12,11 @@ export default function generateHapiPath(path = '', options, serverless) {
hapiPath = `/${options.prefix}${hapiPath}`
}

if (hapiPath !== '/' && hapiPath.endsWith('/')) {
if (
hapiPath !== '/' &&
hapiPath.endsWith('/') &&
(!options.noStripTrailingSlashInUrl || hapiPath.endsWith('+}/'))
) {
hapiPath = hapiPath.slice(0, -1)
}

Expand Down
11 changes: 11 additions & 0 deletions tests/endToEnd/trailingSlash/handler.js
@@ -0,0 +1,11 @@
'use strict'

exports.echo = async (event) => {
return {
statusCode: 200,
body: JSON.stringify({
path: event.path,
resource: event.resource,
}),
}
}
27 changes: 27 additions & 0 deletions tests/endToEnd/trailingSlash/serverless.yml
@@ -0,0 +1,27 @@
service: uncategorized-tests

plugins:
- ../../../

provider:
memorySize: 128
name: aws
region: us-east-1 # default
runtime: nodejs12.x
stage: dev
versionFunctions: false

functions:
echo:
handler: handler.echo
events:
- http:
method: get
path: /echo/test
- http:
method: get
path: /echo/test/
- http:
method: get
path: /echo/{any+}

55 changes: 55 additions & 0 deletions tests/endToEnd/trailingSlash/trailingSlash.test.js
@@ -0,0 +1,55 @@
import { resolve } from 'path'
import fetch from 'node-fetch'
import {
joinUrl,
setup,
teardown,
} from '../../integration/_testHelpers/index.js'

jest.setTimeout(30000)

describe('noStripTrailingSlashInUrl option', () => {
// init
beforeAll(() =>
setup({
servicePath: resolve(__dirname),
args: ['--noStripTrailingSlashInUrl'],
}),
)

// cleanup
afterAll(() => teardown())

describe('when --noStripTrailingSlashInUrl is used, and request is made ending with slash', () => {
test('it should not be removed', async () => {
const url = joinUrl(TEST_BASE_URL, '/dev/echo/something/')
const response = await fetch(url)
const json = await response.json()

expect(json).toEqual({
path: '/echo/something/',
resource: '/echo/{any*}',
})
})
})

describe('when --noStripTrailingSlashInUrl is used, events with and without slash can co-exist', () => {
test('it should not be removed', async () => {
let url = joinUrl(TEST_BASE_URL, '/dev/echo/test')
let response = await fetch(url)
let json = await response.json()
expect(json).toEqual({
path: '/echo/test',
resource: '/echo/test',
})

url = joinUrl(TEST_BASE_URL, '/dev/echo/test/')
response = await fetch(url)
json = await response.json()
expect(json).toEqual({
path: '/echo/test/',
resource: '/echo/test/',
})
})
})
})

0 comments on commit 4dbab1a

Please sign in to comment.