@opra/core 0.33.13 → 1.0.0-alpha.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/cjs/augmentation/18n.augmentation.js +17 -4
- package/cjs/augmentation/http-controller.augmentation.js +25 -0
- package/cjs/constants.js +5 -0
- package/cjs/execution-context.js +25 -12
- package/cjs/{services → helpers}/logger.js +1 -2
- package/cjs/{services/api-service.js → helpers/service-base.js} +8 -8
- package/cjs/http/express-adapter.js +164 -0
- package/cjs/http/http-adapter.js +27 -0
- package/cjs/http/http-context.js +116 -0
- package/cjs/http/impl/asset-cache.js +21 -0
- package/cjs/http/impl/http-handler.js +575 -0
- package/cjs/http/{http-server-request.js → impl/http-incoming.host.js} +21 -46
- package/cjs/http/{http-server-response.js → impl/http-outgoing.host.js} +7 -26
- package/cjs/http/{helpers/multipart-helper.js → impl/multipart-reader.js} +24 -22
- package/cjs/http/impl/{http-incoming-message.host.js → node-incoming-message.host.js} +13 -54
- package/cjs/http/impl/{http-outgoing-message.host.js → node-outgoing-message.host.js} +11 -14
- package/cjs/http/interfaces/http-incoming.interface.js +25 -0
- package/cjs/http/interfaces/http-outgoing.interface.js +22 -0
- package/cjs/http/interfaces/node-incoming-message.interface.js +63 -0
- package/cjs/http/interfaces/node-outgoing-message.interface.js +15 -0
- package/cjs/http/utils/body-reader.js +215 -0
- package/cjs/http/{helpers → utils}/convert-to-raw-headers.js +1 -2
- package/cjs/http/{helpers → utils}/match-known-fields.js +11 -9
- package/cjs/http/utils/wrap-exception.js +34 -0
- package/cjs/index.js +25 -25
- package/cjs/platform-adapter.js +21 -0
- package/cjs/type-guards.js +23 -0
- package/esm/augmentation/18n.augmentation.js +20 -7
- package/esm/augmentation/http-controller.augmentation.js +23 -0
- package/esm/constants.js +2 -0
- package/esm/execution-context.js +25 -13
- package/esm/{services → helpers}/logger.js +1 -2
- package/esm/{services/api-service.js → helpers/service-base.js} +6 -6
- package/esm/http/express-adapter.js +159 -0
- package/esm/http/http-adapter.js +23 -0
- package/esm/http/http-context.js +111 -0
- package/esm/http/impl/asset-cache.js +17 -0
- package/esm/http/impl/http-handler.js +570 -0
- package/esm/http/{http-server-request.js → impl/http-incoming.host.js} +17 -43
- package/esm/http/{http-server-response.js → impl/http-outgoing.host.js} +6 -26
- package/esm/http/{helpers/multipart-helper.js → impl/multipart-reader.js} +22 -20
- package/esm/http/impl/{http-incoming-message.host.js → node-incoming-message.host.js} +11 -52
- package/esm/http/impl/{http-outgoing-message.host.js → node-outgoing-message.host.js} +9 -12
- package/esm/http/interfaces/http-incoming.interface.js +22 -0
- package/esm/http/interfaces/http-outgoing.interface.js +19 -0
- package/esm/http/interfaces/node-incoming-message.interface.js +60 -0
- package/esm/http/interfaces/node-outgoing-message.interface.js +12 -0
- package/esm/http/utils/body-reader.js +210 -0
- package/esm/http/{helpers → utils}/convert-to-headers.js +1 -1
- package/esm/http/{helpers → utils}/convert-to-raw-headers.js +2 -3
- package/esm/http/{helpers → utils}/match-known-fields.js +11 -9
- package/esm/http/utils/wrap-exception.js +30 -0
- package/esm/index.js +25 -26
- package/esm/platform-adapter.js +19 -1
- package/esm/type-guards.js +16 -0
- package/package.json +22 -10
- package/types/augmentation/18n.augmentation.d.ts +32 -2
- package/types/augmentation/http-controller.augmentation.d.ts +21 -0
- package/types/constants.d.ts +2 -0
- package/types/execution-context.d.ts +24 -26
- package/types/helpers/service-base.d.ts +10 -0
- package/types/http/express-adapter.d.ts +13 -0
- package/types/http/http-adapter.d.ts +27 -0
- package/types/http/http-context.d.ts +44 -0
- package/types/http/impl/asset-cache.d.ts +5 -0
- package/types/http/impl/http-handler.d.ts +73 -0
- package/types/http/impl/http-incoming.host.d.ts +23 -0
- package/types/http/impl/http-outgoing.host.d.ts +17 -0
- package/types/http/{helpers/multipart-helper.d.ts → impl/multipart-reader.d.ts} +8 -6
- package/types/http/impl/{http-incoming-message.host.d.ts → node-incoming-message.host.d.ts} +9 -22
- package/types/http/impl/{http-outgoing-message.host.d.ts → node-outgoing-message.host.d.ts} +11 -27
- package/types/http/{http-server-request.d.ts → interfaces/http-incoming.interface.d.ts} +28 -17
- package/types/http/{http-server-response.d.ts → interfaces/http-outgoing.interface.d.ts} +17 -10
- package/types/http/interfaces/node-incoming-message.interface.d.ts +38 -0
- package/types/http/interfaces/node-outgoing-message.interface.d.ts +29 -0
- package/types/http/utils/body-reader.d.ts +41 -0
- package/types/http/utils/wrap-exception.d.ts +2 -0
- package/types/index.d.ts +24 -26
- package/types/platform-adapter.d.ts +20 -48
- package/types/type-guards.d.ts +8 -0
- package/cjs/augmentation/collection.augmentation.js +0 -2
- package/cjs/augmentation/container.augmentation.js +0 -2
- package/cjs/augmentation/resource.augmentation.js +0 -26
- package/cjs/augmentation/singleton.augmentation.js +0 -2
- package/cjs/augmentation/storage.augmentation.js +0 -2
- package/cjs/execution-context.host.js +0 -46
- package/cjs/http/adapters/express-adapter.host.js +0 -34
- package/cjs/http/adapters/express-adapter.js +0 -14
- package/cjs/http/adapters/node-http-adapter.host.js +0 -70
- package/cjs/http/adapters/node-http-adapter.js +0 -14
- package/cjs/http/helpers/json-body-loader.js +0 -29
- package/cjs/http/helpers/query-parsers.js +0 -16
- package/cjs/http/http-adapter-host.js +0 -715
- package/cjs/interfaces/interceptor.interface.js +0 -2
- package/cjs/interfaces/request-handler.interface.js +0 -2
- package/cjs/platform-adapter.host.js +0 -154
- package/cjs/request-context.js +0 -25
- package/cjs/request.host.js +0 -24
- package/cjs/request.js +0 -2
- package/cjs/response.host.js +0 -22
- package/cjs/response.js +0 -2
- package/esm/augmentation/collection.augmentation.js +0 -1
- package/esm/augmentation/container.augmentation.js +0 -1
- package/esm/augmentation/resource.augmentation.js +0 -24
- package/esm/augmentation/singleton.augmentation.js +0 -1
- package/esm/augmentation/storage.augmentation.js +0 -1
- package/esm/execution-context.host.js +0 -42
- package/esm/http/adapters/express-adapter.host.js +0 -30
- package/esm/http/adapters/express-adapter.js +0 -11
- package/esm/http/adapters/node-http-adapter.host.js +0 -65
- package/esm/http/adapters/node-http-adapter.js +0 -11
- package/esm/http/helpers/json-body-loader.js +0 -24
- package/esm/http/helpers/query-parsers.js +0 -12
- package/esm/http/http-adapter-host.js +0 -710
- package/esm/interfaces/interceptor.interface.js +0 -1
- package/esm/interfaces/request-handler.interface.js +0 -1
- package/esm/platform-adapter.host.js +0 -149
- package/esm/request-context.js +0 -22
- package/esm/request.host.js +0 -20
- package/esm/request.js +0 -1
- package/esm/response.host.js +0 -18
- package/esm/response.js +0 -1
- package/i18n/i18n/en/error.json +0 -21
- package/types/augmentation/collection.augmentation.d.ts +0 -146
- package/types/augmentation/container.augmentation.d.ts +0 -14
- package/types/augmentation/resource.augmentation.d.ts +0 -38
- package/types/augmentation/singleton.augmentation.d.ts +0 -83
- package/types/augmentation/storage.augmentation.d.ts +0 -50
- package/types/execution-context.host.d.ts +0 -25
- package/types/http/adapters/express-adapter.d.ts +0 -15
- package/types/http/adapters/express-adapter.host.d.ts +0 -12
- package/types/http/adapters/node-http-adapter.d.ts +0 -17
- package/types/http/adapters/node-http-adapter.host.d.ts +0 -19
- package/types/http/helpers/json-body-loader.d.ts +0 -5
- package/types/http/helpers/query-parsers.d.ts +0 -1
- package/types/http/http-adapter-host.d.ts +0 -34
- package/types/interfaces/interceptor.interface.d.ts +0 -2
- package/types/interfaces/request-handler.interface.d.ts +0 -4
- package/types/platform-adapter.host.d.ts +0 -43
- package/types/request-context.d.ts +0 -13
- package/types/request.d.ts +0 -14
- package/types/request.host.d.ts +0 -27
- package/types/response.d.ts +0 -22
- package/types/response.host.d.ts +0 -22
- package/types/services/api-service.d.ts +0 -10
- /package/cjs/http/{helpers → utils}/common.js +0 -0
- /package/cjs/http/{helpers → utils}/concat-readable.js +0 -0
- /package/cjs/http/{helpers → utils}/convert-to-headers.js +0 -0
- /package/esm/http/{helpers → utils}/common.js +0 -0
- /package/esm/http/{helpers → utils}/concat-readable.js +0 -0
- /package/types/{services → helpers}/logger.d.ts +0 -0
- /package/types/http/{helpers → utils}/common.d.ts +0 -0
- /package/types/http/{helpers → utils}/concat-readable.d.ts +0 -0
- /package/types/http/{helpers → utils}/convert-to-headers.d.ts +0 -0
- /package/types/http/{helpers → utils}/convert-to-raw-headers.d.ts +0 -0
- /package/types/http/{helpers → utils}/match-known-fields.d.ts +0 -0
|
@@ -1,715 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.HttpAdapterHost = void 0;
|
|
4
|
-
const tslib_1 = require("tslib");
|
|
5
|
-
const promises_1 = tslib_1.__importDefault(require("fs/promises"));
|
|
6
|
-
const os_1 = tslib_1.__importDefault(require("os"));
|
|
7
|
-
const valgen_1 = require("valgen");
|
|
8
|
-
const common_1 = require("@opra/common");
|
|
9
|
-
const execution_context_host_js_1 = require("../execution-context.host.js");
|
|
10
|
-
const platform_adapter_host_js_1 = require("../platform-adapter.host.js");
|
|
11
|
-
const request_host_js_1 = require("../request.host.js");
|
|
12
|
-
const request_context_js_1 = require("../request-context.js");
|
|
13
|
-
const response_host_js_1 = require("../response.host.js");
|
|
14
|
-
const json_body_loader_js_1 = require("./helpers/json-body-loader.js");
|
|
15
|
-
const multipart_helper_js_1 = require("./helpers/multipart-helper.js");
|
|
16
|
-
/**
|
|
17
|
-
*
|
|
18
|
-
* @class HttpAdapterHost
|
|
19
|
-
*/
|
|
20
|
-
class HttpAdapterHost extends platform_adapter_host_js_1.PlatformAdapterHost {
|
|
21
|
-
constructor() {
|
|
22
|
-
super(...arguments);
|
|
23
|
-
this._protocol = 'http';
|
|
24
|
-
this._tempDir = os_1.default.tmpdir();
|
|
25
|
-
}
|
|
26
|
-
/**
|
|
27
|
-
* Main http request handler
|
|
28
|
-
* @param incoming
|
|
29
|
-
* @param outgoing
|
|
30
|
-
* @protected
|
|
31
|
-
*/
|
|
32
|
-
async handleHttp(incoming, outgoing) {
|
|
33
|
-
const context = new execution_context_host_js_1.ExecutionContextHost(this.api, this.platform, { http: { incoming, outgoing } });
|
|
34
|
-
try {
|
|
35
|
-
/* istanbul ignore next */
|
|
36
|
-
if (!this._api)
|
|
37
|
-
throw new common_1.InternalServerError(`${Object.getPrototypeOf(this).constructor.name} has not been initialized yet`);
|
|
38
|
-
outgoing.setHeader(common_1.HttpHeaderCodes.X_Opra_Version, common_1.OpraSchema.SpecVersion);
|
|
39
|
-
// Expose headers if cors enabled
|
|
40
|
-
if (outgoing.getHeader(common_1.HttpHeaderCodes.Access_Control_Allow_Origin)) {
|
|
41
|
-
// Expose X-Opra-* headers
|
|
42
|
-
outgoing.appendHeader(common_1.HttpHeaderCodes.Access_Control_Expose_Headers, Object.values(common_1.HttpHeaderCodes)
|
|
43
|
-
.filter(k => k.toLowerCase().startsWith('x-opra-')));
|
|
44
|
-
}
|
|
45
|
-
const { parsedUrl } = incoming;
|
|
46
|
-
if (!parsedUrl.path.length) {
|
|
47
|
-
if (incoming.method === 'GET') {
|
|
48
|
-
outgoing.setHeader('content-type', 'application/json');
|
|
49
|
-
outgoing.end(JSON.stringify(this.api.exportSchema({ webSafe: true })));
|
|
50
|
-
return;
|
|
51
|
-
}
|
|
52
|
-
// Process Batch
|
|
53
|
-
if (incoming.method === 'POST' && incoming.headers['content-type'] === 'multipart/mixed') {
|
|
54
|
-
// todo Process Batch
|
|
55
|
-
}
|
|
56
|
-
throw new common_1.BadRequestError();
|
|
57
|
-
}
|
|
58
|
-
let i = 0;
|
|
59
|
-
let requestProcessed = false;
|
|
60
|
-
const next = async () => {
|
|
61
|
-
const interceptor = this._interceptors[i++];
|
|
62
|
-
if (interceptor) {
|
|
63
|
-
await interceptor(context, next);
|
|
64
|
-
await next();
|
|
65
|
-
}
|
|
66
|
-
else if (!requestProcessed) {
|
|
67
|
-
requestProcessed = true;
|
|
68
|
-
await this.handleExecution(context);
|
|
69
|
-
}
|
|
70
|
-
};
|
|
71
|
-
await next();
|
|
72
|
-
}
|
|
73
|
-
catch (error) {
|
|
74
|
-
if (!outgoing.writableEnded)
|
|
75
|
-
await this.sendErrorResponse(context, [error]);
|
|
76
|
-
}
|
|
77
|
-
finally {
|
|
78
|
-
await context.emitAsync('finish');
|
|
79
|
-
}
|
|
80
|
-
}
|
|
81
|
-
async handleExecution(executionContext) {
|
|
82
|
-
// Parse incoming message and create Request object
|
|
83
|
-
let request;
|
|
84
|
-
try {
|
|
85
|
-
request = await this.parseRequest(executionContext);
|
|
86
|
-
}
|
|
87
|
-
catch (e) {
|
|
88
|
-
if (e instanceof common_1.OpraException)
|
|
89
|
-
throw e;
|
|
90
|
-
const errors = e.issues.map(issue => new common_1.BadRequestError({
|
|
91
|
-
message: issue.message,
|
|
92
|
-
code: 'REQUEST_VALIDATION',
|
|
93
|
-
details: {
|
|
94
|
-
...issue,
|
|
95
|
-
message: undefined
|
|
96
|
-
}
|
|
97
|
-
}));
|
|
98
|
-
return this.sendErrorResponse(executionContext, errors);
|
|
99
|
-
}
|
|
100
|
-
try {
|
|
101
|
-
const { outgoing } = executionContext.switchToHttp();
|
|
102
|
-
const response = new response_host_js_1.ResponseHost({ http: outgoing });
|
|
103
|
-
const context = request_context_js_1.RequestContext.from(executionContext, this.api, request, response);
|
|
104
|
-
await this.executeRequest(context);
|
|
105
|
-
await this.sendResponse(context);
|
|
106
|
-
}
|
|
107
|
-
catch (e) {
|
|
108
|
-
if (e instanceof common_1.OpraException)
|
|
109
|
-
throw e;
|
|
110
|
-
if (e instanceof valgen_1.ValidationError) {
|
|
111
|
-
throw new common_1.InternalServerError({
|
|
112
|
-
message: (0, common_1.translate)('error:RESPONSE_VALIDATION,'),
|
|
113
|
-
code: 'RESPONSE_VALIDATION',
|
|
114
|
-
details: e.issues
|
|
115
|
-
}, e);
|
|
116
|
-
}
|
|
117
|
-
throw new common_1.InternalServerError(e);
|
|
118
|
-
}
|
|
119
|
-
}
|
|
120
|
-
async parseRequest(executionContext) {
|
|
121
|
-
const { incoming } = executionContext.switchToHttp();
|
|
122
|
-
const parsedUrl = new common_1.OpraURL(incoming.url);
|
|
123
|
-
let i = 0;
|
|
124
|
-
let p;
|
|
125
|
-
let resource = this.api.root;
|
|
126
|
-
let request;
|
|
127
|
-
// Walk through container
|
|
128
|
-
while (resource instanceof common_1.Container && i < parsedUrl.path.length) {
|
|
129
|
-
p = parsedUrl.path[i];
|
|
130
|
-
const r = resource.resources.get(p.resource);
|
|
131
|
-
if (r) {
|
|
132
|
-
resource = r;
|
|
133
|
-
if (resource instanceof common_1.Container) {
|
|
134
|
-
i++;
|
|
135
|
-
}
|
|
136
|
-
else
|
|
137
|
-
break;
|
|
138
|
-
}
|
|
139
|
-
else
|
|
140
|
-
break;
|
|
141
|
-
}
|
|
142
|
-
const urlPath = i > 0 ? parsedUrl.path.slice(i) : parsedUrl.path;
|
|
143
|
-
const searchParams = parsedUrl.searchParams;
|
|
144
|
-
// If there is one more element in the path it may be an action
|
|
145
|
-
if (resource instanceof common_1.Container) {
|
|
146
|
-
if (urlPath.length === 1 && resource.actions.has(urlPath[0].resource)) {
|
|
147
|
-
request = await this._parseRequestAction(executionContext, resource, urlPath, searchParams);
|
|
148
|
-
if (request)
|
|
149
|
-
return request;
|
|
150
|
-
}
|
|
151
|
-
}
|
|
152
|
-
else if (urlPath.length === 2 && resource.actions.has(urlPath[1].resource)) {
|
|
153
|
-
request = await this._parseRequestAction(executionContext, resource, urlPath.slice(1), searchParams);
|
|
154
|
-
if (request)
|
|
155
|
-
return request;
|
|
156
|
-
}
|
|
157
|
-
if (resource instanceof common_1.Storage)
|
|
158
|
-
request = await this._parseRequestStorage(executionContext, resource, urlPath.slice(1), searchParams);
|
|
159
|
-
else if (urlPath.length === 1) { // Collection and Singleton resources should be last element in path
|
|
160
|
-
if (resource instanceof common_1.Collection)
|
|
161
|
-
request = await this._parseRequestCollection(executionContext, resource, urlPath, searchParams);
|
|
162
|
-
else if (resource instanceof common_1.Singleton)
|
|
163
|
-
request = await this._parseRequestSingleton(executionContext, resource, urlPath, searchParams);
|
|
164
|
-
}
|
|
165
|
-
if (request)
|
|
166
|
-
return request;
|
|
167
|
-
const path = parsedUrl.path.toString();
|
|
168
|
-
throw new common_1.BadRequestError({
|
|
169
|
-
message: 'No resource or endpoint found at ' + path,
|
|
170
|
-
details: { path }
|
|
171
|
-
});
|
|
172
|
-
}
|
|
173
|
-
async _parseRequestAction(executionContext, resource, urlPath, searchParams) {
|
|
174
|
-
const p = urlPath[0];
|
|
175
|
-
const { controller, endpoint, handler } = await this.getActionHandler(resource, p.resource);
|
|
176
|
-
const { incoming } = executionContext.switchToHttp();
|
|
177
|
-
const contentId = incoming.headers['content-id'];
|
|
178
|
-
const params = this.parseParameters(endpoint.parameters, searchParams);
|
|
179
|
-
return new request_host_js_1.RequestHost({
|
|
180
|
-
endpoint,
|
|
181
|
-
controller,
|
|
182
|
-
handler,
|
|
183
|
-
http: incoming,
|
|
184
|
-
contentId,
|
|
185
|
-
params
|
|
186
|
-
});
|
|
187
|
-
}
|
|
188
|
-
async _parseRequestCollection(executionContext, resource, urlPath, searchParams) {
|
|
189
|
-
const { incoming } = executionContext.switchToHttp();
|
|
190
|
-
if ((incoming.method === 'POST' || incoming.method === 'PATCH') && !incoming.is('json'))
|
|
191
|
-
throw new common_1.BadRequestError({ message: 'Unsupported Content-Type' });
|
|
192
|
-
const contentId = incoming.headers['content-id'];
|
|
193
|
-
const p = urlPath[0];
|
|
194
|
-
switch (incoming.method) {
|
|
195
|
-
case 'POST': {
|
|
196
|
-
if (p.key == null) {
|
|
197
|
-
const { controller, endpoint, handler } = await this.getOperationHandler(resource, 'create');
|
|
198
|
-
const jsonReader = (0, json_body_loader_js_1.jsonBodyLoader)({
|
|
199
|
-
limit: endpoint.options.inputMaxContentSize
|
|
200
|
-
}, endpoint);
|
|
201
|
-
let data = await jsonReader(incoming);
|
|
202
|
-
data = endpoint.decodeInput(data, { coerce: true });
|
|
203
|
-
const params = this.parseParameters(endpoint.parameters, searchParams);
|
|
204
|
-
return new request_host_js_1.RequestHost({
|
|
205
|
-
endpoint,
|
|
206
|
-
controller,
|
|
207
|
-
handler,
|
|
208
|
-
http: incoming,
|
|
209
|
-
contentId,
|
|
210
|
-
data,
|
|
211
|
-
params: {
|
|
212
|
-
...params,
|
|
213
|
-
pick: params.pick && resource.normalizeFieldNames(params.pick),
|
|
214
|
-
omit: params.omit && resource.normalizeFieldNames(params.omit),
|
|
215
|
-
include: params.include && resource.normalizeFieldNames(params.include)
|
|
216
|
-
}
|
|
217
|
-
});
|
|
218
|
-
}
|
|
219
|
-
break;
|
|
220
|
-
}
|
|
221
|
-
case 'DELETE': {
|
|
222
|
-
if (p.key != null) {
|
|
223
|
-
const { controller, endpoint, handler } = await this.getOperationHandler(resource, 'delete');
|
|
224
|
-
const params = this.parseParameters(endpoint.parameters, searchParams);
|
|
225
|
-
return new request_host_js_1.RequestHost({
|
|
226
|
-
endpoint,
|
|
227
|
-
controller,
|
|
228
|
-
handler,
|
|
229
|
-
http: incoming,
|
|
230
|
-
contentId,
|
|
231
|
-
key: resource.parseKeyValue(p.key),
|
|
232
|
-
params
|
|
233
|
-
});
|
|
234
|
-
}
|
|
235
|
-
const { controller, endpoint, handler } = await this.getOperationHandler(resource, 'deleteMany');
|
|
236
|
-
const params = this.parseParameters(endpoint.parameters, searchParams);
|
|
237
|
-
return new request_host_js_1.RequestHost({
|
|
238
|
-
endpoint,
|
|
239
|
-
controller,
|
|
240
|
-
handler,
|
|
241
|
-
http: incoming,
|
|
242
|
-
contentId,
|
|
243
|
-
params: {
|
|
244
|
-
...params,
|
|
245
|
-
filter: params.filter && resource.normalizeFilter(params.filter)
|
|
246
|
-
}
|
|
247
|
-
});
|
|
248
|
-
}
|
|
249
|
-
case 'GET': {
|
|
250
|
-
if (p.key != null) {
|
|
251
|
-
const { controller, endpoint, handler } = await this.getOperationHandler(resource, 'get');
|
|
252
|
-
const params = this.parseParameters(endpoint.parameters, searchParams);
|
|
253
|
-
return new request_host_js_1.RequestHost({
|
|
254
|
-
endpoint,
|
|
255
|
-
controller,
|
|
256
|
-
handler,
|
|
257
|
-
http: incoming,
|
|
258
|
-
contentId,
|
|
259
|
-
key: resource.parseKeyValue(p.key),
|
|
260
|
-
params: {
|
|
261
|
-
...params,
|
|
262
|
-
pick: params.pick && resource.normalizeFieldNames(params.pick),
|
|
263
|
-
omit: params.omit && resource.normalizeFieldNames(params.omit),
|
|
264
|
-
include: params.include && resource.normalizeFieldNames(params.include)
|
|
265
|
-
}
|
|
266
|
-
});
|
|
267
|
-
}
|
|
268
|
-
const { controller, endpoint, handler } = await this.getOperationHandler(resource, 'findMany');
|
|
269
|
-
const params = this.parseParameters(endpoint.parameters, searchParams);
|
|
270
|
-
return new request_host_js_1.RequestHost({
|
|
271
|
-
endpoint,
|
|
272
|
-
controller,
|
|
273
|
-
handler,
|
|
274
|
-
http: incoming,
|
|
275
|
-
contentId,
|
|
276
|
-
params: {
|
|
277
|
-
...params,
|
|
278
|
-
pick: params.pick && resource.normalizeFieldNames(params.pick),
|
|
279
|
-
omit: params.omit && resource.normalizeFieldNames(params.omit),
|
|
280
|
-
include: params.include && resource.normalizeFieldNames(params.include),
|
|
281
|
-
sort: params.sort && resource.normalizeSortFields(params.sort),
|
|
282
|
-
filter: params.filter && resource.normalizeFilter(params.filter)
|
|
283
|
-
}
|
|
284
|
-
});
|
|
285
|
-
}
|
|
286
|
-
case 'PATCH': {
|
|
287
|
-
if (p.key != null) {
|
|
288
|
-
const { controller, endpoint, handler } = await this.getOperationHandler(resource, 'update');
|
|
289
|
-
const jsonReader = (0, json_body_loader_js_1.jsonBodyLoader)({
|
|
290
|
-
limit: endpoint.options.inputMaxContentSize
|
|
291
|
-
}, endpoint);
|
|
292
|
-
let data = await jsonReader(incoming);
|
|
293
|
-
data = endpoint.decodeInput(data, { coerce: true, partial: true });
|
|
294
|
-
const params = this.parseParameters(endpoint.parameters, searchParams);
|
|
295
|
-
return new request_host_js_1.RequestHost({
|
|
296
|
-
endpoint,
|
|
297
|
-
controller,
|
|
298
|
-
handler,
|
|
299
|
-
http: incoming,
|
|
300
|
-
contentId,
|
|
301
|
-
key: resource.parseKeyValue(p.key),
|
|
302
|
-
data,
|
|
303
|
-
params: {
|
|
304
|
-
...params,
|
|
305
|
-
pick: params.pick && resource.normalizeFieldNames(params.pick),
|
|
306
|
-
omit: params.omit && resource.normalizeFieldNames(params.omit),
|
|
307
|
-
include: params.include && resource.normalizeFieldNames(params.include),
|
|
308
|
-
}
|
|
309
|
-
});
|
|
310
|
-
}
|
|
311
|
-
const { controller, endpoint, handler } = await this.getOperationHandler(resource, 'updateMany');
|
|
312
|
-
const jsonReader = (0, json_body_loader_js_1.jsonBodyLoader)({
|
|
313
|
-
limit: endpoint.options.inputMaxContentSize
|
|
314
|
-
}, endpoint);
|
|
315
|
-
let data = await jsonReader(incoming);
|
|
316
|
-
data = endpoint.decodeInput(data, { coerce: true, partial: true });
|
|
317
|
-
const params = this.parseParameters(endpoint.parameters, searchParams);
|
|
318
|
-
return new request_host_js_1.RequestHost({
|
|
319
|
-
endpoint,
|
|
320
|
-
controller,
|
|
321
|
-
handler,
|
|
322
|
-
http: incoming,
|
|
323
|
-
contentId,
|
|
324
|
-
data,
|
|
325
|
-
params: {
|
|
326
|
-
...params,
|
|
327
|
-
filter: params.filter && resource.normalizeFilter(params.filter)
|
|
328
|
-
}
|
|
329
|
-
});
|
|
330
|
-
}
|
|
331
|
-
}
|
|
332
|
-
throw new common_1.MethodNotAllowedError({
|
|
333
|
-
message: `Collection resource doesn't accept http "${incoming.method}" method`
|
|
334
|
-
});
|
|
335
|
-
}
|
|
336
|
-
async _parseRequestSingleton(executionContext, resource, urlPath, searchParams) {
|
|
337
|
-
const { incoming } = executionContext.switchToHttp();
|
|
338
|
-
if ((incoming.method === 'POST' || incoming.method === 'PATCH') && !incoming.is('json'))
|
|
339
|
-
throw new common_1.BadRequestError({ message: 'Unsupported Content-Type' });
|
|
340
|
-
const contentId = incoming.headers['content-id'];
|
|
341
|
-
switch (incoming.method) {
|
|
342
|
-
case 'POST': {
|
|
343
|
-
const { controller, endpoint, handler } = await this.getOperationHandler(resource, 'create');
|
|
344
|
-
const jsonReader = (0, json_body_loader_js_1.jsonBodyLoader)({
|
|
345
|
-
limit: endpoint.options.inputMaxContentSize
|
|
346
|
-
}, endpoint);
|
|
347
|
-
let data = await jsonReader(incoming);
|
|
348
|
-
data = endpoint.decodeInput(data, { coerce: true });
|
|
349
|
-
const params = this.parseParameters(endpoint.parameters, searchParams);
|
|
350
|
-
return new request_host_js_1.RequestHost({
|
|
351
|
-
endpoint,
|
|
352
|
-
controller,
|
|
353
|
-
handler,
|
|
354
|
-
http: incoming,
|
|
355
|
-
contentId,
|
|
356
|
-
data,
|
|
357
|
-
params: {
|
|
358
|
-
...params,
|
|
359
|
-
pick: params.pick && resource.normalizeFieldNames(params.pick),
|
|
360
|
-
omit: params.omit && resource.normalizeFieldNames(params.omit),
|
|
361
|
-
include: params.include && resource.normalizeFieldNames(params.include)
|
|
362
|
-
}
|
|
363
|
-
});
|
|
364
|
-
}
|
|
365
|
-
case 'DELETE': {
|
|
366
|
-
const { controller, endpoint, handler } = await this.getOperationHandler(resource, 'delete');
|
|
367
|
-
const params = this.parseParameters(endpoint.parameters, searchParams);
|
|
368
|
-
return new request_host_js_1.RequestHost({
|
|
369
|
-
endpoint,
|
|
370
|
-
controller,
|
|
371
|
-
handler,
|
|
372
|
-
http: incoming,
|
|
373
|
-
contentId,
|
|
374
|
-
params
|
|
375
|
-
});
|
|
376
|
-
}
|
|
377
|
-
case 'GET': {
|
|
378
|
-
const { controller, endpoint, handler } = await this.getOperationHandler(resource, 'get');
|
|
379
|
-
const params = this.parseParameters(endpoint.parameters, searchParams);
|
|
380
|
-
return new request_host_js_1.RequestHost({
|
|
381
|
-
endpoint,
|
|
382
|
-
controller,
|
|
383
|
-
handler,
|
|
384
|
-
http: incoming,
|
|
385
|
-
contentId,
|
|
386
|
-
params: {
|
|
387
|
-
...params,
|
|
388
|
-
pick: params.pick && resource.normalizeFieldNames(params.pick),
|
|
389
|
-
omit: params.omit && resource.normalizeFieldNames(params.omit),
|
|
390
|
-
include: params.include && resource.normalizeFieldNames(params.include)
|
|
391
|
-
}
|
|
392
|
-
});
|
|
393
|
-
}
|
|
394
|
-
case 'PATCH': {
|
|
395
|
-
const { controller, endpoint, handler } = await this.getOperationHandler(resource, 'update');
|
|
396
|
-
const jsonReader = (0, json_body_loader_js_1.jsonBodyLoader)({
|
|
397
|
-
limit: endpoint.options.inputMaxContentSize
|
|
398
|
-
}, endpoint);
|
|
399
|
-
let data = await jsonReader(incoming);
|
|
400
|
-
data = endpoint.decodeInput(data, { coerce: true, partial: true });
|
|
401
|
-
const params = this.parseParameters(endpoint.parameters, searchParams);
|
|
402
|
-
return new request_host_js_1.RequestHost({
|
|
403
|
-
endpoint,
|
|
404
|
-
controller,
|
|
405
|
-
handler,
|
|
406
|
-
http: incoming,
|
|
407
|
-
contentId,
|
|
408
|
-
data,
|
|
409
|
-
params: {
|
|
410
|
-
...params,
|
|
411
|
-
pick: params.pick && resource.normalizeFieldNames(params.pick),
|
|
412
|
-
omit: params.omit && resource.normalizeFieldNames(params.omit),
|
|
413
|
-
include: params.include && resource.normalizeFieldNames(params.include),
|
|
414
|
-
}
|
|
415
|
-
});
|
|
416
|
-
}
|
|
417
|
-
}
|
|
418
|
-
throw new common_1.MethodNotAllowedError({
|
|
419
|
-
message: `Singleton resource doesn't accept http "${incoming.method}" method`
|
|
420
|
-
});
|
|
421
|
-
}
|
|
422
|
-
async _parseRequestStorage(executionContext, resource, urlPath, searchParams) {
|
|
423
|
-
const { incoming } = executionContext.switchToHttp();
|
|
424
|
-
const contentId = incoming.headers['content-id'];
|
|
425
|
-
switch (incoming.method) {
|
|
426
|
-
case 'GET': {
|
|
427
|
-
const { controller, endpoint, handler } = await this.getOperationHandler(resource, 'get');
|
|
428
|
-
const params = this.parseParameters(endpoint.parameters, searchParams);
|
|
429
|
-
return new request_host_js_1.RequestHost({
|
|
430
|
-
endpoint,
|
|
431
|
-
controller,
|
|
432
|
-
handler,
|
|
433
|
-
http: incoming,
|
|
434
|
-
contentId,
|
|
435
|
-
path: urlPath.toString().substring(1),
|
|
436
|
-
params
|
|
437
|
-
});
|
|
438
|
-
}
|
|
439
|
-
case 'DELETE': {
|
|
440
|
-
const { controller, endpoint, handler } = await this.getOperationHandler(resource, 'delete');
|
|
441
|
-
const params = this.parseParameters(endpoint.parameters, searchParams);
|
|
442
|
-
return new request_host_js_1.RequestHost({
|
|
443
|
-
endpoint,
|
|
444
|
-
controller,
|
|
445
|
-
handler,
|
|
446
|
-
http: incoming,
|
|
447
|
-
contentId,
|
|
448
|
-
path: urlPath.toString().substring(1),
|
|
449
|
-
params
|
|
450
|
-
});
|
|
451
|
-
}
|
|
452
|
-
case 'POST': {
|
|
453
|
-
const { controller, endpoint, handler } = await this.getOperationHandler(resource, 'post');
|
|
454
|
-
const params = this.parseParameters(endpoint.parameters, searchParams);
|
|
455
|
-
await promises_1.default.mkdir(this._tempDir, { recursive: true });
|
|
456
|
-
const multipartIterator = await multipart_helper_js_1.MultipartIterator.create(incoming, {
|
|
457
|
-
...endpoint.options,
|
|
458
|
-
filename: () => this.serviceName + '_p' + process.pid +
|
|
459
|
-
't' + String(Date.now()).substring(8) + 'r' + (0, common_1.uid)(12)
|
|
460
|
-
});
|
|
461
|
-
multipartIterator.pause();
|
|
462
|
-
// Add an hook to clean up files after request finished
|
|
463
|
-
executionContext.on('finish', async () => {
|
|
464
|
-
multipartIterator.cancel();
|
|
465
|
-
await multipartIterator.deleteFiles().catch(() => void 0);
|
|
466
|
-
});
|
|
467
|
-
return new request_host_js_1.RequestHost({
|
|
468
|
-
endpoint,
|
|
469
|
-
controller,
|
|
470
|
-
handler,
|
|
471
|
-
http: incoming,
|
|
472
|
-
contentId,
|
|
473
|
-
parts: multipartIterator,
|
|
474
|
-
path: urlPath.toString().substring(1),
|
|
475
|
-
params
|
|
476
|
-
});
|
|
477
|
-
}
|
|
478
|
-
}
|
|
479
|
-
throw new common_1.MethodNotAllowedError({
|
|
480
|
-
message: `Storage resource doesn't accept http "${incoming.method}" method`
|
|
481
|
-
});
|
|
482
|
-
}
|
|
483
|
-
parseParameters(paramDefs, searchParams) {
|
|
484
|
-
const out = {};
|
|
485
|
-
const onFail = (issue) => {
|
|
486
|
-
issue.message = `Parameter parse error. ` + issue.message;
|
|
487
|
-
issue.location = '@parameters';
|
|
488
|
-
return issue;
|
|
489
|
-
};
|
|
490
|
-
// Parse known parameters
|
|
491
|
-
for (const [k, prm] of paramDefs.entries()) {
|
|
492
|
-
const decode = prm.getDecoder();
|
|
493
|
-
let v = searchParams?.getAll(k);
|
|
494
|
-
try {
|
|
495
|
-
if (!v.length && prm.default != null)
|
|
496
|
-
v = [prm.default];
|
|
497
|
-
if (!prm.isArray) {
|
|
498
|
-
v = v[0];
|
|
499
|
-
v = decode(v, { coerce: true, label: k, onFail });
|
|
500
|
-
}
|
|
501
|
-
else {
|
|
502
|
-
v = v.map(x => decode(x, { coerce: true, label: k })).flat();
|
|
503
|
-
if (!v.length)
|
|
504
|
-
v = undefined;
|
|
505
|
-
}
|
|
506
|
-
if (v !== undefined)
|
|
507
|
-
out[k] = v;
|
|
508
|
-
}
|
|
509
|
-
catch (e) {
|
|
510
|
-
e.message = `Error parsing parameter ${k}. ` + e.message;
|
|
511
|
-
throw e;
|
|
512
|
-
}
|
|
513
|
-
}
|
|
514
|
-
// Add unknown parameters
|
|
515
|
-
if (searchParams) {
|
|
516
|
-
for (const k of searchParams.keys()) {
|
|
517
|
-
let v = searchParams.getAll(k);
|
|
518
|
-
if (v.length < 2)
|
|
519
|
-
v = v[0];
|
|
520
|
-
if (!paramDefs.has(k))
|
|
521
|
-
out[k] = v;
|
|
522
|
-
}
|
|
523
|
-
}
|
|
524
|
-
return out;
|
|
525
|
-
}
|
|
526
|
-
async executeRequest(context) {
|
|
527
|
-
const { request } = context;
|
|
528
|
-
const { response } = context;
|
|
529
|
-
const { endpoint, resource, handler } = request;
|
|
530
|
-
// Call endpoint handler method
|
|
531
|
-
let value;
|
|
532
|
-
try {
|
|
533
|
-
value = await handler.call(request.controller, context);
|
|
534
|
-
if (response.value == null)
|
|
535
|
-
response.value = value;
|
|
536
|
-
// Normalize response value
|
|
537
|
-
if (endpoint.kind === 'operation') {
|
|
538
|
-
if (resource instanceof common_1.Collection || resource instanceof common_1.Singleton || resource instanceof common_1.Storage) {
|
|
539
|
-
const operationName = endpoint.name;
|
|
540
|
-
if (operationName === 'delete' || operationName === 'deleteMany' || operationName === 'updateMany') {
|
|
541
|
-
let affected = 0;
|
|
542
|
-
if (typeof value === 'number')
|
|
543
|
-
affected = value;
|
|
544
|
-
else if (typeof value === 'boolean')
|
|
545
|
-
affected = value ? 1 : 0;
|
|
546
|
-
else if (typeof value === 'object')
|
|
547
|
-
affected = value.affected || value.affectedRows ||
|
|
548
|
-
(operationName === 'updateMany' ? value.updated : value.deleted);
|
|
549
|
-
response.value = affected;
|
|
550
|
-
return;
|
|
551
|
-
}
|
|
552
|
-
if (resource instanceof common_1.Collection || resource instanceof common_1.Singleton) {
|
|
553
|
-
// "get" and "update" endpoints must return the entity instance, otherwise it means resource not found
|
|
554
|
-
if (value == null && (operationName === 'get' || operationName === 'update'))
|
|
555
|
-
throw new common_1.ResourceNotAvailableError(resource.name, request.key);
|
|
556
|
-
// "findMany" endpoint should return array of entity instances
|
|
557
|
-
if (operationName === 'findMany')
|
|
558
|
-
value = (value == null ? [] : Array.isArray(value) ? value : [value]);
|
|
559
|
-
else
|
|
560
|
-
value = value == null ? {} : Array.isArray(value) ? value[0] : value;
|
|
561
|
-
}
|
|
562
|
-
value = endpoint.encodeReturning(value, { coerce: true });
|
|
563
|
-
response.value = value;
|
|
564
|
-
return;
|
|
565
|
-
}
|
|
566
|
-
}
|
|
567
|
-
if (response.value)
|
|
568
|
-
response.value = endpoint.encodeReturning(response.value, { coerce: true });
|
|
569
|
-
}
|
|
570
|
-
catch (error) {
|
|
571
|
-
response.errors.push(error);
|
|
572
|
-
}
|
|
573
|
-
}
|
|
574
|
-
async sendResponse(context) {
|
|
575
|
-
const { request, response } = context;
|
|
576
|
-
const { endpoint, resource } = request;
|
|
577
|
-
const outgoing = response.switchToHttp();
|
|
578
|
-
if (response.errors?.length || (outgoing.statusCode >= 400 && outgoing.statusCode <= 599))
|
|
579
|
-
return this.sendErrorResponse(context, response.errors || []);
|
|
580
|
-
// if response redirected we do not send any response
|
|
581
|
-
if (outgoing.statusCode >= 300 && outgoing.statusCode < 400) {
|
|
582
|
-
outgoing.end();
|
|
583
|
-
return;
|
|
584
|
-
}
|
|
585
|
-
let contentType = String(outgoing.getHeader('content-type') || '');
|
|
586
|
-
let returnType = endpoint.returnType;
|
|
587
|
-
if (endpoint.kind === 'action' && !contentType && endpoint.returnMime && response.value) {
|
|
588
|
-
contentType = endpoint.returnMime;
|
|
589
|
-
outgoing.setHeader('Content-Type', contentType);
|
|
590
|
-
}
|
|
591
|
-
// OperationResult response
|
|
592
|
-
if ((returnType || endpoint.kind === 'operation') &&
|
|
593
|
-
!(resource instanceof common_1.Storage && endpoint.name === 'get')) {
|
|
594
|
-
const incoming = context.switchToHttp().incoming;
|
|
595
|
-
const apiUrl = new common_1.OpraURL(incoming.baseUrl, incoming.protocol + '://' + incoming.get('host')).toString();
|
|
596
|
-
const body = new common_1.OperationResult({
|
|
597
|
-
context: '',
|
|
598
|
-
contextUrl: ''
|
|
599
|
-
});
|
|
600
|
-
const operationName = endpoint.kind === 'operation' ? endpoint.name : '';
|
|
601
|
-
if (operationName === 'delete' || operationName === 'deleteMany' || operationName === 'updateMany') {
|
|
602
|
-
body.affected = response.value;
|
|
603
|
-
returnType = undefined;
|
|
604
|
-
}
|
|
605
|
-
else {
|
|
606
|
-
outgoing.statusCode = outgoing.statusCode || common_1.HttpStatusCode.OK;
|
|
607
|
-
if (operationName === 'create')
|
|
608
|
-
outgoing.statusCode = 201;
|
|
609
|
-
if (operationName === 'update' || operationName === 'create') {
|
|
610
|
-
body.affected = response.value ? 1 : 0;
|
|
611
|
-
}
|
|
612
|
-
if (operationName === 'findMany') {
|
|
613
|
-
body.count = response.value.length;
|
|
614
|
-
body.totalMatches = response.totalMatches;
|
|
615
|
-
}
|
|
616
|
-
}
|
|
617
|
-
if (returnType) {
|
|
618
|
-
if (response.value == null)
|
|
619
|
-
throw new common_1.InternalServerError(`"${request.endpoint.name}" endpoint should return value`);
|
|
620
|
-
if (!returnType.isEmbedded) {
|
|
621
|
-
const ns = this.api.getDataTypeNs(returnType);
|
|
622
|
-
// const isOpraSpec = returnType.document.url?.startsWith('https://oprajs.com/spec/v1.0')
|
|
623
|
-
body.type = (ns ? ns + ':' : '') + returnType.name;
|
|
624
|
-
body.typeUrl =
|
|
625
|
-
(ns
|
|
626
|
-
? new common_1.OpraURL('/#/types/' + returnType.name, returnType.document.url || 'http://tempuri.org').toString()
|
|
627
|
-
: apiUrl + '/#/types/' + returnType.name);
|
|
628
|
-
}
|
|
629
|
-
else
|
|
630
|
-
body.typeUrl = body.contextUrl + '/type';
|
|
631
|
-
if (response.value instanceof common_1.OperationResult) {
|
|
632
|
-
Object.assign(body, response.value);
|
|
633
|
-
}
|
|
634
|
-
else
|
|
635
|
-
body.payload = response.value;
|
|
636
|
-
body.payload = this.i18n.deep(body.payload);
|
|
637
|
-
}
|
|
638
|
-
body.context = endpoint.getFullPath(false);
|
|
639
|
-
body.contextUrl = apiUrl + '/#' + endpoint.getFullPath(true);
|
|
640
|
-
outgoing.setHeader(common_1.HttpHeaderCodes.Content_Type, 'application/opra+json; charset=utf-8');
|
|
641
|
-
outgoing.send(JSON.stringify(body));
|
|
642
|
-
outgoing.end();
|
|
643
|
-
return;
|
|
644
|
-
}
|
|
645
|
-
outgoing.statusCode = outgoing.statusCode || common_1.HttpStatusCode.OK;
|
|
646
|
-
if (response.value != null) {
|
|
647
|
-
if (typeof response.value === 'string') {
|
|
648
|
-
if (!contentType)
|
|
649
|
-
outgoing.setHeader('content-type', 'text/plain');
|
|
650
|
-
outgoing.send(response.value);
|
|
651
|
-
}
|
|
652
|
-
else if (Buffer.isBuffer(response.value) || (0, common_1.isReadable)(response.value)) {
|
|
653
|
-
if (!contentType)
|
|
654
|
-
outgoing.setHeader('content-type', 'application/octet-stream');
|
|
655
|
-
outgoing.send(response.value);
|
|
656
|
-
}
|
|
657
|
-
else {
|
|
658
|
-
outgoing.setHeader('content-type', 'application/json; charset=utf-8');
|
|
659
|
-
outgoing.send(JSON.stringify(response.value));
|
|
660
|
-
}
|
|
661
|
-
}
|
|
662
|
-
outgoing.end();
|
|
663
|
-
}
|
|
664
|
-
async sendErrorResponse(context, errors) {
|
|
665
|
-
const { outgoing } = context.switchToHttp();
|
|
666
|
-
if (outgoing.headersSent) {
|
|
667
|
-
outgoing.end();
|
|
668
|
-
return;
|
|
669
|
-
}
|
|
670
|
-
if (!errors.length)
|
|
671
|
-
errors.push((0, common_1.wrapException)({ status: outgoing.statusCode || 500 }));
|
|
672
|
-
errors.forEach(x => {
|
|
673
|
-
if (x instanceof common_1.OpraException) {
|
|
674
|
-
switch (x.severity) {
|
|
675
|
-
case "fatal":
|
|
676
|
-
this._logger.fatal(x);
|
|
677
|
-
break;
|
|
678
|
-
case "warning":
|
|
679
|
-
this._logger.warn(x);
|
|
680
|
-
break;
|
|
681
|
-
default:
|
|
682
|
-
this._logger.error(x);
|
|
683
|
-
}
|
|
684
|
-
}
|
|
685
|
-
else
|
|
686
|
-
this._logger.fatal(x);
|
|
687
|
-
});
|
|
688
|
-
const wrappedErrors = errors.map(common_1.wrapException);
|
|
689
|
-
// Sort errors from fatal to info
|
|
690
|
-
wrappedErrors.sort((a, b) => {
|
|
691
|
-
const i = common_1.IssueSeverity.Keys.indexOf(a.severity) - common_1.IssueSeverity.Keys.indexOf(b.severity);
|
|
692
|
-
if (i === 0)
|
|
693
|
-
return b.status - a.status;
|
|
694
|
-
return i;
|
|
695
|
-
});
|
|
696
|
-
let status = outgoing.statusCode || 0;
|
|
697
|
-
if (!status || status < Number(common_1.HttpStatusCode.BAD_REQUEST)) {
|
|
698
|
-
status = wrappedErrors[0].status;
|
|
699
|
-
if (status < Number(common_1.HttpStatusCode.BAD_REQUEST))
|
|
700
|
-
status = common_1.HttpStatusCode.INTERNAL_SERVER_ERROR;
|
|
701
|
-
}
|
|
702
|
-
outgoing.statusCode = status;
|
|
703
|
-
const body = new common_1.OperationResult({
|
|
704
|
-
errors: wrappedErrors.map(x => this._i18n.deep(x.toJSON()))
|
|
705
|
-
});
|
|
706
|
-
outgoing.setHeader(common_1.HttpHeaderCodes.Content_Type, 'application/opra+json; charset=utf-8');
|
|
707
|
-
outgoing.setHeader(common_1.HttpHeaderCodes.Cache_Control, 'no-cache');
|
|
708
|
-
outgoing.setHeader(common_1.HttpHeaderCodes.Pragma, 'no-cache');
|
|
709
|
-
outgoing.setHeader(common_1.HttpHeaderCodes.Expires, '-1');
|
|
710
|
-
outgoing.setHeader(common_1.HttpHeaderCodes.X_Opra_Version, common_1.OpraSchema.SpecVersion);
|
|
711
|
-
outgoing.send(JSON.stringify(body));
|
|
712
|
-
outgoing.end();
|
|
713
|
-
}
|
|
714
|
-
}
|
|
715
|
-
exports.HttpAdapterHost = HttpAdapterHost;
|