3
3
// Copyright 2019-Present Datadog, Inc.
4
4
5
5
import { FULL_NAME_BUNDLERS } from '@dd/core/constants' ;
6
+ import { runServer } from '@dd/core/helpers/server' ;
6
7
import { ROOT } from '@dd/tools/constants' ;
7
8
import chalk from 'chalk' ;
8
9
import { Command , Option } from 'clipanion' ;
9
- import fs from 'fs' ;
10
- import http from 'http' ;
10
+ import type http from 'http' ;
11
11
import template from 'lodash.template' ;
12
- import path from 'path' ;
13
-
14
- const MIME_TYPES = {
15
- default : 'application/octet-stream' ,
16
- html : 'text/html; charset=UTF-8' ,
17
- js : 'application/javascript' ,
18
- css : 'text/css' ,
19
- png : 'image/png' ,
20
- jpg : 'image/jpg' ,
21
- gif : 'image/gif' ,
22
- ico : 'image/x-icon' ,
23
- svg : 'image/svg+xml' ,
24
- } as const ;
25
12
26
13
// Some context to use for templating content with {{something}}.
27
14
const CONTEXT : Record < string , readonly string [ ] > = {
@@ -31,15 +18,6 @@ const CONTEXT: Record<string, readonly string[]> = {
31
18
// Templating regex.
32
19
const INTERPOLATE_RX = / { { ( [ \s \S ] + ?) } } / g;
33
20
34
- // Promise to boolean.
35
- const toBool = [ ( ) => true , ( ) => false ] ;
36
-
37
- type File = {
38
- found : boolean ;
39
- ext : keyof typeof MIME_TYPES ;
40
- content : string ;
41
- } ;
42
-
43
21
class DevServer extends Command {
44
22
static paths = [ [ 'dev-server' ] ] ;
45
23
@@ -115,57 +93,39 @@ class DevServer extends Command {
115
93
return fileContext ;
116
94
}
117
95
118
- async prepareFile ( requestUrl : string , context : Record < string , string > ) : Promise < File > {
119
- const staticPath = this . root
120
- ? path . isAbsolute ( this . root )
121
- ? this . root
122
- : path . resolve ( ROOT , this . root )
123
- : ROOT ;
124
- const url = new URL ( requestUrl , 'http://127.0.0.1' ) ;
125
- const paths = [ staticPath , url . pathname ] ;
126
-
127
- if ( url . pathname . endsWith ( '/' ) ) {
128
- paths . push ( 'index.html' ) ;
129
- }
130
-
131
- const filePath = path . join ( ...paths ) ;
132
- const pathTraversal = ! filePath . startsWith ( staticPath ) ;
133
- const exists = await fs . promises . access ( filePath ) . then ( ...toBool ) ;
134
- const found = ! pathTraversal && exists ;
135
- const finalPath = found ? filePath : `${ staticPath } /404.html` ;
136
- const ext = path . extname ( finalPath ) . substring ( 1 ) . toLowerCase ( ) as File [ 'ext' ] ;
137
- const fileContent = template ( await fs . promises . readFile ( finalPath , { encoding : 'utf-8' } ) , {
138
- interpolate : INTERPOLATE_RX ,
139
- } ) ( context ) ;
140
-
141
- return { found, ext, content : fileContent } ;
142
- }
143
-
144
96
async execute ( ) {
145
- http . createServer ( async ( req , res ) => {
146
- try {
97
+ runServer ( {
98
+ port : + this . port ,
99
+ root : this . root ,
100
+ middleware : async ( resp , req ) => {
101
+ const statusCode = resp . statusCode ;
147
102
const context = this . getContext ( req ) ;
148
- const file = await this . prepareFile ( req . url || '/' , context ) ;
149
- const statusCode = file . found ? 200 : 404 ;
150
- const mimeType = MIME_TYPES [ file . ext ] || MIME_TYPES . default ;
151
- const c = statusCode === 200 ? chalk . green : chalk . yellow . bold ;
152
-
153
- res . writeHead ( statusCode , {
103
+ const content = template ( resp . body , {
104
+ interpolate : INTERPOLATE_RX ,
105
+ } ) ( context ) ;
106
+ const headers = {
154
107
'Set-Cookie' : `context_cookie=${ encodeURIComponent ( JSON . stringify ( context ) ) } ;SameSite=Strict;` ,
155
- 'Content-Type' : mimeType ,
156
- } ) ;
108
+ } ;
157
109
158
- res . end ( file . content ) ;
110
+ const c =
111
+ {
112
+ 200 : chalk . green ,
113
+ 404 : chalk . yellow . bold ,
114
+ 500 : chalk . red . bold ,
115
+ } [ statusCode ] || chalk . white ;
159
116
160
117
console . log ( ` -> [${ c ( statusCode . toString ( ) ) } ] ${ req . method } ${ req . url } ` ) ;
161
- } catch ( e : any ) {
162
- res . writeHead ( 500 , { 'Content-Type' : MIME_TYPES . html } ) ;
163
- res . end ( 'Internal Server Error' ) ;
164
- const c = chalk . red . bold ;
165
- console . log ( ` -> [${ c ( '500' ) } ] ${ req . method } ${ req . url } : ${ e . message } ` ) ;
166
- console . log ( e ) ;
167
- }
168
- } ) . listen ( this . port ) ;
118
+ if ( resp . error ) {
119
+ console . log ( resp . error ) ;
120
+ }
121
+
122
+ return {
123
+ statusCode : resp . statusCode ,
124
+ headers,
125
+ body : content ,
126
+ } ;
127
+ } ,
128
+ } ) ;
169
129
console . log ( `Server running at http://127.0.0.1:${ this . port } /` ) ;
170
130
}
171
131
}
0 commit comments