icon |
---|
icons8:up-round |
h3 v2 includes some behavior and API changes that you need to consider applying when migrating.
Note
Currently v2 is in beta stage You can try with h3-nightly@2x
Note
This is an undergoing migration guide and is not finished yet.
H3 v2 is rewritten based on Web standard primitives (URL
, Headers
, Request
, and Response
).
event.node
context is only available when running in Node.js runtime and event.web
is available via event.request
.
On Node.js runtime, h3 uses a two way proxy to sync Node.js API with Web standard API making it a seamless experience on Node.
Old utils for plain handler and web handler are removed to embrace web standards.
You should always explicitly return
the response body.
If you were previously using methods below, you can replace them with return
statements returning a text, JSON, stream, or web Response
(h3 smartly detects and handles each):
send(event, value)
: Migrate toreturn <value>
.sendError(event, <error>)
: Migrate tothrow createError(<error>)
.sendStream(event, <stream>)
: Migrate toreturn <stream>
.sendWebResponse(event, <response>)
: Migrate toreturn <response>
.
Other send utils that are renamed and need explicit return
:
sendNoContent(event)
/return null
: Migrate toreturn noContent(event)
.sendIterable(event, <value>)
: Migrate toreturn iterable(event, <value>)
.sendRedirect(event, location, code)
: Migrate toreturn redirect(event, location, code)
.sendProxy(event, target)
: Migrate toreturn proxy(event, target)
.handleCors(event)
: Check return value (boolean) and earlyreturn
if handled.serveStatic(event, content)
: Make sure to addreturn
before.
Router functionality is now integrated into the h3 app core. Instead of createApp()
and createRouter()
you can use createH3()
.
New methods:
app.use(handler)
: Adds a global middleware.app.use(route, handler)
: Adds a routed middleware.app.on(method, handler)
/app.all(handler)
/app.[METHOD](handler)
: Adds a route handler.
Handlers will run in this order:
- All global middleware in the same order were registered
- All routed middleware from least specific to most specific paths (auto-sorted)
- Matched route handler
Any handler can return a response. If middleware don't return a response, next handlers will be tried and finally make a 404 if neither responses. Router handlers can return or not return any response, in this case, h3 will send a simple 200 with empty content.
h3 migrated to a brand new route-matching engine unjs/rou3. You might experience slight (but more intuitive) behavior changes for matching patterns.
Other changes from v1:
- Handlers registered with
app.use("/path", handler)
only match/path
(not/path/foo/bar
). For matching all subpaths like before, it should be updated toapp.use("/path/**", handler)
. - The
event.path
received in each handler will have a full path without omitting the prefixes. usewithBase(base, handler)
utility to make prefixed app. (example:withBase("/api", app.handler)
). app.use(() => handler, { lazy: true })
is no supported anymore. Instead you can useapp.use(defineLazyEventHandler(() => handler), { lazy: true })
.app.use(["/path1", "/path2"], ...)
andapp.use("/path", [handler1, handler2])
are not supported anymore. Instead, use multipleapp.use()
calls.- Custom
match
function forapp.use
is not supported anymore (middleware can skip themselves). app.resolve(path) => { route, handler }
changed toapp.resolve(method, path) => { method, route, handler }
.router.use(path, handler)
is deprecated. Userouter.all(path, handler)
instead.router.add(path, method: Method | Method[]
signature is changed torouter.add(method: Method, path)
(important)
Most of request body utilities can now be replaced with event.request
utils which is based on standard Request
interface.
readBody(event)
utility will use JSON.parse
or URLSearchParams
for parsing requests with application/x-www-form-urlencoded
content-type.
- For text: Use event.request.text().
- For json: Use event.request.json().
- For formData: Use event.request.formData().
- For stream: Use event.request.body.
Behavior changes:
- Body utils won't throw an error if the incoming request has no body (or is a
GET
method for example) but instead, return empty values. - Native
request.json
andreadBody
does not use unjs/destr anymore. You should always filter and sanitize data coming from user to avoid prototype-poisoning.
h3 migrated to leverage standard web Headers
for all utils.
Header values are always a plain string
now (no null
or undefined
or number
or string[]
).
For the Set-Cookie
header, you can use headers.getSetCookie
that always returns a string array.
h3 v2 deprecated some legacy and aliased utilities.
App and router:
createApp
/createRouter
: Migrate tocreateH3()
.
Handler:
eventHandler
: Migrate todefineEventHandler
(or remove it!).lazyEventHandler
: Migrate todefineLazyEventHandler
.toEventHandler
/isEventHandler
: (removed) Any function can be an event handler.useBase
: Migrate towithbase
.
Request:
getHeader
/getRequestHeader
: Migrate toevent.request.headers.get(name)
.getHeaders
/getRequestHeaders
: Migrate toObject.fromEntries(event.request.headers.entries())
.getRequestPath
: Migrate toevent.path
orevent.url
.getMethod
: Migrate toevent.method
.
Response:
getResponseHeader
/getResponseHeaders
: Migrate toevent.response.headers.get(name)
setHeader
/setResponseHeader
/setHeaders
/setResponseHeaders
: Migrate toevent.response.headers.set(name, value)
.appendHeader
/appendResponseHeader
/appendResponseHeaders
: Migrate toevent.response.headers.append(name, value)
.removeResponseHeader
/clearResponseHeaders
: Migrate toevent.response.headers.delete(name)
appendHeaders
: Migrate toappendResponseHeaders
.defaultContentType
: Migrate toevent.response.headers.set("content-type", type)
getResponseStatus
/getResponseStatusText
/setResponseStatus
: Useevent.response.status
andevent.response.statusText
.
Node.js:
defineNodeListener
: Migrate todefineNodeHandler
.fromNodeMiddleware
: Migrate tofromNodeHandler
.toNodeListener
: Migrate totoNodeHandler
.createEvent
: (removed): Use Node.js adapter (toNodeHandler(app)
).fromNodeRequest
: (removed): Use Node.js adapter (toNodeHandler(app)
).promisifyNodeListener
(removed).callNodeListener
: (removed).
Web:
fromPlainHandler
: (removed) Migrate to Web API.toPlainHandler
: (removed) Migrate to Web API.fromPlainRequest
(removed) Migrate to Web API or usemockEvent
util for testing.callWithPlainRequest
(removed) Migrate to Web API.fromWebRequest
: (removed) Migrate to Web API.callWithWebRequest
: (removed).
Body:
readRawBody
: Migrate toevent.request.text()
orevent.request.arrayBuffer()
.getBodyStream
/getRequestWebStream
: Migrate toevent.request.body
.readFormData
/readMultipartFormData
/readFormDataBody
: Migrate toevent.request.formData()
.
Utils:
isStream
: Migrate toinstanceof ReadableStream
.isWebResponse
: Migrate toinstanceof Response
.splitCookiesString
: UsesplitSetCookieString
from cookie-es.MIMES
: (removed).
Types:
App
: Migrate toH3
.AppOptions
: Migrate toH3Config
._RequestMiddleware
: Migrate toRequestMiddleware
._ResponseMiddleware
: Migrate toResponseMiddleware
.NodeListener
: Migrate toNodeHandler
.TypedHeaders
: Migrate toRequestHeaders
andResponseHeaders
.HTTPHeaderName
: Migrate toRequestHeaderName
andResponseHeaderName
.H3Headers
: Migrate to nativeHeaders
.H3Response
: Migrate to nativeResponse
.MultiPartData
: Migrate to nativeFormData
.RouteNode
: Migrate toRouterEntry
.CreateRouterOptions
: Migrate toRouterOptions
.
Removed type exports: WebEventContext
, NodeEventContext
, NodePromisifiedHandler
, AppUse
, Stack
, InputLayer
, InputStack
, Layer
, Matcher
, PlainHandler
, PlainRequest
, PlainResponse
, WebHandler
.