1+ // servedir HTTP Server
2+ // https://github.com/rem/servedir
3+
4+ // Copyright 2011, Remy Sharp
5+ // http://remysharp.com
6+
7+ // Convenience aliases.
8+ var createServer = require ( 'http' ) . createServer , parse = require ( 'url' ) . parse , path = require ( 'path' ) , fs = require ( 'fs' ) , types ,
9+
10+ // Matches control characters in URLs.
11+ escapable = / [ \x00 - \x1f \x7f " ' & ? $ \x20 + , : ; = @ < > # % { } | \\ \^ ~ \[ \] ` ] / g,
12+
13+ // Escape sequences and entities for control characters.
14+ escapes = {
15+ '&' : '&' ,
16+ '<' : '<' ,
17+ '>' : '>' ,
18+ '"' : '"' ,
19+ '\'' : '''
20+ } ,
21+
22+ // The `servedir` function creates a new simple HTTP server.
23+ servedir = module . exports = function ( root , port ) {
24+ if ( typeof root != 'string' ) root = servedir . defaultRoot ;
25+ if ( typeof port != 'number' ) port = servedir . defaultPort ;
26+ // Create a new HTTP server.
27+ var server = createServer ( function ( req , res ) {
28+ // Resolve the path to the requested file or folder.
29+ var pathname = parse ( decodeURIComponent ( req . url ) ) . pathname , file = path . join ( root , pathname ) ;
30+ path . exists ( file , function ( exists ) {
31+ if ( ! exists ) {
32+ res . writeHead ( 404 , { 'Content-Type' : 'text/plain' } ) ;
33+ res . end ( 'The file ' + file + ' was not found.' ) ;
34+ } else {
35+ // Serve files and directories.
36+ fs . stat ( file , function ( err , stats ) {
37+ if ( err ) {
38+ // Internal server error; avoid throwing an exception.
39+ res . writeHeader ( 500 , { 'Content-Type' : 'text/plain' } ) ;
40+ res . end ( 'An internal server error occurred: ' + err ) ;
41+ } else if ( stats . isFile ( ) ) {
42+ // Read and serve files.
43+ fs . readFile ( file , 'binary' , function ( err , contents ) {
44+ if ( err ) {
45+ // Internal server error; avoid throwing an exception.
46+ res . writeHeader ( 500 , { 'Content-Type' : 'text/plain' } ) ;
47+ res . write ( 'An internal server error occurred: ' + err ) ;
48+ } else {
49+ // Set the correct MIME type using the extension.
50+ res . writeHead ( 200 , { 'Content-Type' : types [ path . extname ( file ) . slice ( 1 ) ] || servedir . defaultType } ) ;
51+ res . write ( contents , 'binary' ) ;
52+ }
53+ // Close the connection.
54+ res . end ( ) ;
55+ } ) ;
56+ } else {
57+ // Automatically append a trailing slash for directories.
58+ if ( pathname . charAt ( pathname . length - 1 ) != '/' ) pathname += '/' ;
59+ fs . readdir ( file , function ( err , files ) {
60+ if ( err ) {
61+ res . writeHeader ( 500 , { 'Content-Type' : 'text/plain' } ) ;
62+ res . write ( 'An internal server error occurred: ' + err ) ;
63+ } else {
64+ // Create a basic directory listing.
65+ files = files . map ( function ( name ) {
66+ // URL-encode the path to each file or directory.
67+ return '<a href="' + ( pathname + name ) . replace ( escapable , function ( match ) {
68+ // Cache escape sequences not already in the escapes hash.
69+ return escapes [ match ] || ( escapes [ match ] = '%' + match . charCodeAt ( 0 ) . toString ( 16 ) ) ;
70+ } ) + '">' + name + '</a>' ;
71+ } ) ;
72+ // Add a link to the root directory.
73+ if ( pathname != '/' ) files . unshift ( '<a href="..">..</a>' ) ;
74+ res . writeHead ( 200 , { 'Content-Type' : 'text/html' } ) ;
75+ res . write ( '<!DOCTYPE html><meta charset=utf-8><title>[dir] ' + file + '</title><ul><li>' + files . join ( '<li>' ) + '</ul>' ) ;
76+ }
77+ res . end ( ) ;
78+ } ) ;
79+ }
80+ } ) ;
81+ }
82+ } ) ;
83+ } ) ;
84+ server . listen ( port ) ;
85+ return server ;
86+ } ;
87+
88+ // The current version of `servedir`. Keep in sync with `package.json`.
89+ servedir . version = '0.1.5' ;
90+
91+ // The default MIME type, root directory, and port.
92+ servedir . defaultType = 'application/octet-stream' ;
93+ servedir . defaultRoot = '.' ;
94+ servedir . defaultPort = 8000 ;
95+
96+ // Common MIME types.
97+ servedir . types = types = {
98+ 'aiff' : 'audio/x-aiff' ,
99+ 'appcache' : 'text/cache-manifest' ,
100+ 'atom' : 'application/atom+xml' ,
101+ 'bmp' : 'image/bmp' ,
102+ 'crx' : 'application/x-chrome-extension' ,
103+ 'css' : 'text/css' ,
104+ 'eot' : 'application/vnd.ms-fontobject' ,
105+ 'gif' : 'image/gif' ,
106+ 'htc' : 'text/x-component' ,
107+ 'html' : 'text/html' ,
108+ 'ico' : 'image/vnd.microsoft.icon' ,
109+ 'ics' : 'text/calendar' ,
110+ 'jpeg' : 'image/jpeg' ,
111+ 'js' : 'text/javascript' ,
112+ 'json' : 'application/json' ,
113+ 'mathml' : 'application/mathml+xml' ,
114+ 'midi' : 'audio/midi' ,
115+ 'mov' : 'video/quicktime' ,
116+ 'mp3' : 'audio/mpeg' ,
117+ 'mp4' : 'video/mp4' ,
118+ 'mpeg' : 'video/mpeg' ,
119+ 'ogg' : 'video/ogg' ,
120+ 'otf' : 'font/opentype' ,
121+ 'pdf' : 'application/pdf' ,
122+ 'png' : 'image/png' ,
123+ 'rtf' : 'application/rtf' ,
124+ 'sh' : 'application/x-sh' ,
125+ 'svg' : 'image/svg+xml' ,
126+ 'swf' : 'application/x-shockwave-flash' ,
127+ 'tar' : 'application/x-tar' ,
128+ 'tiff' : 'image/tiff' ,
129+ 'ttf' : 'font/truetype' ,
130+ 'txt' : 'text/plain' ,
131+ 'wav' : 'audio/x-wav' ,
132+ 'webm' : 'video/webm' ,
133+ 'webp' : 'image/webp' ,
134+ 'woff' : 'font/woff' ,
135+ 'xhtml' : 'application/xhtml+xml' ,
136+ 'xml' : 'text/xml' ,
137+ 'xsl' : 'application/xml' ,
138+ 'xslt' : 'application/xslt+xml' ,
139+ 'zip' : 'application/zip'
140+ } ;
141+
142+ // MIME type aliases for different extensions.
143+ types . aif = types . aiff ;
144+ types . htm = types . html ;
145+ types . jpe = types . jpg = types . jpeg ;
146+ types . jsonp = types . js ;
147+ types . manifest = types . appcache ;
148+ types . mid = types . midi ;
149+ types . mpg = types . mpeg ;
150+ types . ogv = types . ogg ;
151+ types . rb = types . txt ;
152+ types . svgz = types . svg ;
153+ types . tif = types . tiff ;
154+ types . xht = types . xhtml ;
0 commit comments