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:
parent
1dc52dbc6c
commit
e3e0a68b9a
|
@ -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 p = join(__dirname, '../client/next-prefetcher-bundle.js')
|
||||
await serveStatic(req, res, p)
|
||||
})
|
||||
const routes = {
|
||||
'/_next-prefetcher.js': async (req, res, params) => {
|
||||
const p = join(__dirname, '../client/next-prefetcher-bundle.js')
|
||||
await this.serveStatic(req, res, p)
|
||||
},
|
||||
|
||||
this.router.get('/_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)
|
||||
})
|
||||
'/_next/:buildId/main.js': async (req, res, params) => {
|
||||
this.handleBuildId(params.buildId, res)
|
||||
const p = join(this.dir, '.next/main.js')
|
||||
await this.serveStaticWithGzip(req, res, p)
|
||||
},
|
||||
|
||||
this.router.get('/_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)
|
||||
})
|
||||
'/_next/:buildId/commons.js': async (req, res, params) => {
|
||||
this.handleBuildId(params.buildId, res)
|
||||
const p = join(this.dir, '.next/commons.js')
|
||||
await this.serveStaticWithGzip(req, res, p)
|
||||
},
|
||||
|
||||
this.router.get('/_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)
|
||||
})
|
||||
'/_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) => {
|
||||
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)
|
||||
})
|
||||
'/_next/:path+': async (req, res, params) => {
|
||||
const p = join(__dirname, '..', 'client', ...(params.path || []))
|
||||
await this.serveStatic(req, res, p)
|
||||
},
|
||||
|
||||
this.router.get('/:path*', async (req, res) => {
|
||||
const { pathname, query } = parse(req.url, true)
|
||||
await this.render(req, res, pathname, query)
|
||||
})
|
||||
'/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) {
|
||||
|
|
|
@ -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) {
|
||||
|
|
|
@ -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 })
|
||||
|
|
Loading…
Reference in a new issue