1
0
Fork 0
mirror of https://github.com/terribleplan/next.js.git synced 2024-01-19 02:48:18 +00:00

Fix handling http methods (#748)

* support HEAD method

* respond with 501 if method is not GET or HEAD
This commit is contained in:
Naoyuki Kanezawa 2017-01-13 00:38:43 +09:00 committed by Guillermo Rauch
parent 1dc52dbc6c
commit e3e0a68b9a
3 changed files with 60 additions and 49 deletions

View file

@ -1,7 +1,7 @@
import { resolve, join } from 'path'
import { parse } from 'url'
import fs from 'mz/fs'
import http from 'http'
import http, { STATUS_CODES } from 'http'
import {
renderToHTML,
renderErrorToHTML,
@ -38,7 +38,7 @@ export default class Server {
.catch((err) => {
if (!this.quiet) console.error(err)
res.statusCode = 500
res.end('error')
res.end(STATUS_CODES[500])
})
}
}
@ -67,43 +67,52 @@ export default class Server {
}
defineRoutes () {
this.router.get('/_next-prefetcher.js', async (req, res, params) => {
const routes = {
'/_next-prefetcher.js': async (req, res, params) => {
const p = join(__dirname, '../client/next-prefetcher-bundle.js')
await serveStatic(req, res, p)
})
await this.serveStatic(req, res, p)
},
this.router.get('/_next/:buildId/main.js', async (req, res, params) => {
'/_next/:buildId/main.js': async (req, res, params) => {
this.handleBuildId(params.buildId, res)
const p = join(this.dir, '.next/main.js')
await serveStaticWithGzip(req, res, p)
})
await this.serveStaticWithGzip(req, res, p)
},
this.router.get('/_next/:buildId/commons.js', async (req, res, params) => {
'/_next/:buildId/commons.js': async (req, res, params) => {
this.handleBuildId(params.buildId, res)
const p = join(this.dir, '.next/commons.js')
await serveStaticWithGzip(req, res, p)
})
await this.serveStaticWithGzip(req, res, p)
},
this.router.get('/_next/:buildId/pages/:path*', async (req, res, params) => {
'/_next/:buildId/pages/:path*': async (req, res, params) => {
this.handleBuildId(params.buildId, res)
const paths = params.path || ['index']
const pathname = `/${paths.join('/')}`
await this.renderJSON(req, res, pathname)
})
},
this.router.get('/_next/:path+', async (req, res, params) => {
'/_next/:path+': async (req, res, params) => {
const p = join(__dirname, '..', 'client', ...(params.path || []))
await serveStatic(req, res, p)
})
this.router.get('/static/:path+', async (req, res, params) => {
const p = join(this.dir, 'static', ...(params.path || []))
await serveStatic(req, res, p)
})
await this.serveStatic(req, res, p)
},
this.router.get('/:path*', async (req, res) => {
'/static/:path+': async (req, res, params) => {
const p = join(this.dir, 'static', ...(params.path || []))
await this.serveStatic(req, res, p)
},
'/:path*': async (req, res) => {
const { pathname, query } = parse(req.url, true)
await this.render(req, res, pathname, query)
})
}
}
for (const method of ['GET', 'HEAD']) {
for (const p of Object.keys(routes)) {
this.router.add(method, p, routes[p])
}
}
}
async start (port) {
@ -125,8 +134,14 @@ export default class Server {
const fn = this.router.match(req, res)
if (fn) {
await fn()
} else {
return
}
if (req.method === 'GET' || req.method === 'HEAD') {
await this.render404(req, res)
} else {
res.statusCode = 501
res.end(STATUS_CODES[501])
}
}
@ -135,7 +150,7 @@ export default class Server {
res.setHeader('X-Powered-By', `Next.js ${pkg.version}`)
}
const html = await this.renderToHTML(req, res, pathname, query)
sendHTML(res, html)
sendHTML(res, html, req.method)
}
async renderToHTML (req, res, pathname, query) {
@ -163,7 +178,7 @@ export default class Server {
async renderError (err, req, res, pathname, query) {
const html = await this.renderErrorToHTML(err, req, res, pathname, query)
sendHTML(res, html)
sendHTML(res, html, req.method)
}
async renderErrorToHTML (err, req, res, pathname, query) {
@ -191,7 +206,7 @@ export default class Server {
async render404 (req, res) {
const { pathname, query } = parse(req.url, true)
res.statusCode = 404
this.renderErrorToHTML(null, req, res, pathname, query)
this.renderError(null, req, res, pathname, query)
}
async renderJSON (req, res, page) {

View file

@ -14,7 +14,7 @@ import App from '../lib/app'
export async function render (req, res, pathname, query, opts) {
const html = await renderToHTML(req, res, pathname, opts)
sendHTML(res, html)
sendHTML(res, html, req.method)
}
export function renderToHTML (req, res, pathname, query, opts) {
@ -23,7 +23,7 @@ export function renderToHTML (req, res, pathname, query, opts) {
export async function renderError (err, req, res, pathname, query, opts) {
const html = await renderErrorToHTML(err, req, res, query, opts)
sendHTML(res, html)
sendHTML(res, html, req.method)
}
export function renderErrorToHTML (err, req, res, pathname, query, opts = {}) {
@ -111,24 +111,24 @@ export async function renderErrorJSON (err, req, res, { dir = process.cwd(), dev
sendJSON(res, {
component,
err: err && dev ? errorToJSON(err) : null
})
}, req.method)
}
export function sendHTML (res, html) {
export function sendHTML (res, html, method) {
if (res.finished) return
res.setHeader('Content-Type', 'text/html')
res.setHeader('Content-Length', Buffer.byteLength(html))
res.end(html)
res.end(method === 'HEAD' ? null : html)
}
export function sendJSON (res, obj) {
export function sendJSON (res, obj, method) {
if (res.finished) return
const json = JSON.stringify(obj)
res.setHeader('Content-Type', 'application/json')
res.setHeader('Content-Length', Buffer.byteLength(json))
res.end(json)
res.end(method === 'HEAD' ? null : json)
}
function errorToJSON (err) {

View file

@ -8,10 +8,6 @@ export default class Router {
this.routes = new Map()
}
get (path, fn) {
this.add('GET', path, fn)
}
add (method, path, fn) {
const routes = this.routes.get(method) || new Set()
routes.add({ match: route(path), fn })