http-svc
Version:
A HTTP request service for browser and node.js
89 lines (82 loc) • 2.87 kB
text/typescript
import { HttpSvcMiddleware } from '@http-svc/middleware'
import { IMiddlewareHandler, BuiltInMiddlewareName, IHttpSvcContext } from 'types/exports'
import { IBodyPayload } from 'types/middlewares/body'
import {
getBuiltInMiddlewareName,
buildURL,
ContentType,
isEqualContentType,
getContentType,
setContentType,
paramsSerializer
} from '../shared'
const jsonBody = (ctx: IHttpSvcContext, data: Record<string, unknown>, contentType?: string) => {
if (!ctx.request) return
ctx.request.data = JSON.stringify(data)
if (!ctx.request.headers) {
const headers: Record<string, string> = {}
setContentType(headers, ContentType.JSON)
ctx.request.headers = headers
} else if (!contentType) {
setContentType(ctx.request.headers, ContentType.JSON)
}
}
const body: IMiddlewareHandler<IBodyPayload> = async function (ctx, next, config) {
if (!ctx.request) return next()
const { params, headers } = ctx.request
// 处理query到url上
const ps = config?.payload?.paramsSerializer
ctx.request.url = buildURL(ctx.request.url, params || {}, ps)
// 如果是post,需要将body处理好准备请求
if (ctx.request.data) {
// 这些对象不处理,只处理Record
const isContinue = Object.prototype.toString.call(ctx.request.data) !== '[object Object]'
if (!isContinue) {
const contentType = getContentType(headers)
const data = ctx.request.data as Record<string, unknown>
if (config?.payload?.stringify) {
jsonBody(ctx, data, contentType)
return await next()
}
if (isEqualContentType(ContentType.Form, contentType)) {
if (typeof ps === 'function') {
ctx.request.data = ps(data)
} else {
const qsOptions: qs.IStringifyOptions = {
encode: true,
arrayFormat: 'brackets'
}
if (ps && typeof ps === 'object') {
Object.assign(qsOptions, ps)
}
ctx.request.data = paramsSerializer(data, qsOptions)
}
}
if (isEqualContentType(ContentType.JSON, contentType || ContentType.JSON)) {
jsonBody(ctx, data, contentType)
}
if (isEqualContentType(ContentType.FormData, contentType)) {
const keys = Object.keys(data)
if (keys.length) {
ctx.request.data = keys.reduce((form, key) => {
const value = data[key]
if (value instanceof Blob || typeof value === 'string') {
form.append(key, value)
} else {
form.append(key, String(value))
}
return form
}, new FormData())
}
}
}
}
return await next()
}
export class HttpSvcBody extends HttpSvcMiddleware<IBodyPayload> {
static handler = body
name: BuiltInMiddlewareName = getBuiltInMiddlewareName('BODY')
constructor() {
super(body)
}
}