web_server 2.0.0

  • readme.md
  • changelog.md
  • Installing
  • Versions
  • --

WebServer

An efficient server library for quickly creating a WebServer and handling HTTP requests, WebSocket connections, and routing API requests using the Dart language.

Includes extra nice features, such as setting a parameter to require Basic Authentication for a Url, with all of the difficult auth checking and responding taken care of by the server, plus much more!

Who is using this package?

SocialFlare

  • Used for preprocessing and serving webpages and resources, serving API responses, and multiple other features.
  • Major backer: Guarantees long-term support for this project's concept. Thank you, SocialFlare!

Ebates, Inc.

  • For a handful of internal tools for organizing data and serving stat pages.
  • Used to serve a realtime Purchases Stat information webpage to merchant representatives at the Ebates MAX Conference built around this package.

Use Example (for no coding needed)

You can use this WebServer to serve files without even having to code a single line. Using Dart's pub global activate feature, you can add the WebServer package as an executable to call from the command line in any directory and serve files from it.

# Activate the WebServer globally.
pub global activate web_server
# Navigate to the Directory that you want to serve files from.
cd /path/to/directory

# Activate the WebServer on that Directory. Defaults to port 8080.
# http://127.0.0.1:8080/path/to/file
web_server

Features & Use Example (for coders)

Please check out the "example/" folder in this package for full details.

For processing HTML like PHP

Use Angular-like variables, which will be converted using a helper method from this package (see Dart code below).

=== index.html ===

<body>
  <h1>Welcome, {{username}}!</h1>

  <p>The date today is: {{todayDate}}.</p>
</body>

Then, process variables like PHP on the Dart server side:

=== main.dart ===

import "dart:io";
import "package:web_server/web_server.dart" as webServer;

void main() {
  // Initialize the WebServer  
  final webServer.WebServer localWebServer = new webServer.WebServer(InternetAddress.ANY_IP_V4, 8080,
        hasHttpServer: true);
        
  localWebServer.httpServerHandler
    .forRequestPath(new webServer.UrlPath('/index.html')).onRequested.listen((final HttpRequest httpRequest) async {
      String indexFileContents = await new File('path/to/index.html').readAsString();
      
      // Apply the Dart variables to the HTML file's variables like
      // AngularJS/AngularDart
      indexFileContents = webServer.applyVarModifiers(indexFileContents, {
        "username": "mrDude",
        "todayDate": '${new DateTime.now()}'
      });
      
      httpRequest.response
          ..headers.contentType = new ContentType('text', 'html', charset: 'utf-8')
          ..write(indexFileContents)
          ..close();
    });
}

For Hosting APIs

Filter every request starting with a certain Url pattern into a request handler.

import "dart:io";
import "package:web_server/web_server.dart" as webServer;

void main() {
  // Initialize the WebServer
  final webServer.WebServer localWebServer = new webServer.WebServer(InternetAddress.ANY_IP_V4, 8080,
        hasHttpServer: true);
        
  localWebServer.httpServerHandler
      // NOTE: ApiHandler would be a Class or namespace created by you in your code, for example.
      ..handleRequestsStartingWith(new webServer.UrlPath('/api/categories')).listen(ApiHandler.forCategories)
      ..handleRequestsStartingWith(new webServer.UrlPath('/api/products')).listen(ApiHandler.forProducts)
      ..handleRequestsStartingWith(new webServer.UrlPath('/api/users')).listen((final HttpRequest httpRequest) {
        // Create the Object for the response
        final webServer.ApiResponse apiResponse = new webServer.ApiResponse()
            ..addData("username", "mrDude") // Add data
            ..addData("email", "radical_surfer@example.com")
            ..addData("userId", 1425302);

        // Send the data back through to the request
        httpRequest.response
            // Set to "application/json; charset=utf-8"
            ..headers.contentType = ContentType.JSON
            
            // Stringify the JSON output, then send to client
            ..write(apiResponse.toJsonEncoded())
            
            ..close();
      });
}

Static File Directory/Basic WebServer

import "dart:io";
import "dart:async";
import "package:web_server/web_server.dart" as webServer;

Future<Null> main() async {
  // Initialize the WebServer  
  final webServer.WebServer localWebServer = new webServer.WebServer(InternetAddress.ANY_IP_V4, 8080,
        hasHttpServer: true);
        
  // Attach HttpServer pages and event handlers
  await localWebServer.httpServerHandler
      // Automatically recursively parse and serve all items in this
      // directory matching the accepted file types (optional parameter).
      .serveStaticVirtualDirectory('web',
          supportedFileExtensions: const <String>['html', 'css', 'dart', 'js'], // Optional restriction
          shouldPreCache: true);
}

WebSocket Server

Let the WebServer automatically handle upgrading and connecting to WebSockets from the client side. The WebServer will forward data related to important events and automatically call your event listeners if you send data through a WebSocket from the client with the "cmd" parameter in the payload's Map Object.

import "dart:io";
import "package:web_server/web_server.dart" as webServer;

void main() {
  // Initialize the WebServer with the hasWebSocketServer parameter
  final webServer.WebServer localWebServer = new webServer.WebServer(InternetAddress.ANY_IP_V4, 8080,
          hasHttpServer: true, hasWebSocketServer: true);
          
  // HTTP Server handlers code here...
  
  // Attach WebSocket command listeners and base events
  localWebServer.webSocketServerHandler
      // For automatically routing handling of data sent through a WebSocket with this pattern of "cmd":
      // {"cmd": 0, "data": { "pokemonCount": 151 }}
      ..on[0].listen((final webServer.WebSocketRequestPayload requestPayload) { /*...*/ })
      ..onConnectionOpen.listen((final webServer.WebSocketConnectionData connectionData) { /*...*/ })
      ..onConnectionError.listen((final WebSocket webSocket) { /*...*/ })
      ..onConnectionClose.listen((final WebSocket webSocket) { /*...*/ });
}

Add a custom ContentType

Allows the server to automatically pick up on this file extension as the supplied ContentType parameter when it is handling serving files.

HttpServerRequestHandler.addContentType('.html', new ContentType('text', 'html', charset: 'utf-8'));

Features and bugs

Please file feature requests and bugs using the GitHub issue tracker for this repository.

Using this package? Let me know!

I am excited to see if other developers are able to make something neat with this package. If you have a project using it, please send me a quick email at the email address listed on my GitHub's main page. Thanks a bunch!

WebServer Changelog

v2.0.0 (12.20.2015)

  • HttpServerRequestHandler: Added content types for .mp3, .ogg, .oga, .ogv.
  • HttpServerRequestHandler: Changed the _fileExtensions content types over to using the ContentType Object instead of a List<String> and having to build the ContentType Object for every request; also, removed the declaration of it being a 'const' so that a developer using the server would be able to add their own new content types programatically.
  • HttpServerRequestHandler: Some code clean-up and optimizations for the occasional variable reuse optimization or the similar.
  • HttpServerRequestHandler: Created a new format for listening for webpage path requests to make it easier to understand and more intuitive by making the event format similar to binding DOM events on a webpage, like, for example, the format of querySelector('...').onClick.listen((_) {}).
  • WebServer: Added a new constructor for binding a secure server and switched the syntax to using the new Dart 1.13 BoringSSL format instead of the old NSS method; use the new WebServer.secure() constructor to support this.
  • WebServer: Removed the 'GET' and 'POST' allowedMethods default value so that any type of request header will be allowed by default; the developer will no longer have to specify every type of allowed request method.
  • WebServer: Bumped the default wait time for a response to generate from the server code (response deadline) from 20 seconds to 30 seconds to allow for more complex response generation to not catch the developer off guard as quickly in case the developer isn't coding with this deadline in mind.
  • Improved some of the verbose error logging by including the name of the Class and method in the error text to make debugging easier (especially if manually working with a forked version of this repo and learning how it works).
  • HttpServerRequestHandler: Added a method and structures for opening the ability for developers using this package to add their own custom error code handlers using .onErrorDocument().
  • Updated the examples files to demonstrate some of this release's API changes and additions.
  • HttpServerRequestHandler: Deprecated serveVirtualDirectory() in favor of the clearer and having more features, like being dynamic, serveStaticVirtualDirectory() and serveDynamicVirtualDirectory() (arriving eventually; a.k.a. coming soon).
  • HttpServerRequestHandler: Renamed the UrlData Class to UrlPath to make it easier to understand what the Object is representing.
  • Added an bin/ directory and an executable rule to the Pubspec to enable using this package with pub global activate and running a server right from a directory using the command line without even having to write any code! It's as simple as the web_server command from the terminal, and it will serve that directory as a serveStaticVirtualDirectory() command.
  • HttpServerRequestHandler (serveStaticVirtualDirectory): Made the requirement of providing a whitelist of supported file extensions an optional parameter to allow for serving an entire directory, or a directory with flexible file types, simple and not requiring a server restart; also, this makes it possible for the pub global web_server command to operate with any directory's files.
  • Updates to the ReadMe for the new methods and features; clarified and demonstrated features that might not have been as well-known or exemplified before; added a testimonial for my work using this package in many side projects and work-requested projects at Ebates.
  • HttpServerRequestHandler: Removed a loop that was checking file extensions on every file entity for a match in the serveStaticVirtualDirectory and is now doing a .contains() on the List to be much faster and loop less.
  • HttpServerRequestHandler (serveStaticVirtualDirectory): Removed the redundant isRelativePath parameter.
  • HttpServerRequestHandler (serveStaticVirtualDirectory): Now, there is a parameter to enable pre-caching for files in this static Directory to make reads pull from memory instead of the FileSystem, which will be much faster and economical.
  • Updated the code examples directory files to reflect the new API changes and additions.
  • ReadMe: Added a section asking other developers to let me know if they are making something exciting using my Dart package.
  • HttpServerRequestHandler: Improved the helper methods for sending 404 and 500 errors easily with sendPageNotFoundResponse() and sendInternalServerErrorResponse(); will now use the supplied custom error response HTML from the developer, if provided.
  • HttpServerRequestHandler (serveStaticFile): Automatically detects relative file paths and more efficiently resolves the relative path to access the static file; removed the redundant isRelativePath parameter.
  • ReadMe: Clarification to some of the code examples and section titles; added details about SocialFlare to the "Who is using this package?" section.
  • LICENSE: Added a LICENSE file to allow other developers to use this code and for compatibility with the Dart Pub requirements.

v1.1.4 (5.14.2015)

  • Found that HttpRequest paths were not matching serveVirtualDirectory() generated paths on Windows machines because the Url would be something like: '/main.dart' and Windows would provide and store a path segment with the opposite separator at '\main.dart' resulting in the String comparison to fail; this has been resolved.

v1.1.3 (5.9.2015)

  • Added a handleRequestsStartingWith() method for intercepting requests starting with a specified string; this is useful for handling everything in API patterns such as starting with '/api/'; added an example to the examples folder in "example/web_server.dart".

v1.1.2 (5.5.2015)

  • Removed a single inefficient .runtimeType use.
  • Changed a mimetype definition and added more.
  • Images and some binary sources were loading incorrectly, so switching to directly piping the file contents into the HttpResponse, instead of reading, then adding.
  • Fixed issue with the file extension not matching in serveVirtualDirectory if the extension was not all lowercase.
  • Solved issue with file and directory path building that would assemble incorrectly on Windows machines.
  • Changed the serveVirtualDirectory() parameter for "includeDirNameInPath" to "includeContainerDirNameInPath" for parameter meaning clarity.
  • Fixed a broken try/catch when loading a virtual file for a request.
  • Made _VirtualDirectoryFileData easier to use by adding getters with clearer meaning such as .absoluteFileSystemPath and .httpRequestPath.
  • Greatly improved the efficiency of serveStandardFile for certain binary file formats and nicely improved speed and memory for all binary file formats.
  • Removed UTF-8 from being the default charset for non-matched mimetypes in binary files.
  • Removed diffent handling in serveStandardFile based on the mimetype and now all use the same piping to the HttpResponse.
  • Included another log into shouldBeVerbose guide.
  • Nicely clarified some confusing parts of the code.

v1.1.1 (4.26.2015)

  • Removing the default UTF-8 charset requirement in the response header to allow for different file encodings; will re-add the charset soon when encoding detection (appears to be difficult at the moment) is implemented.
  • Handling for non-UTF8 file encoding by piping the file bytes directly into the response without passing through a string decoder first; last release, I understood this differently and the behavior was not what I wanted it to behave as; stinkin' byte encoding detection.
  • Will re-add the byte encoding to the content-type header soon; I really don't like leaving this out in requests, but don't want to prevent clients from serving non-UTF8 files until this can be determined.

v1.1.0 (4.25.2015)

  • Renamed the WebServer.webServer library to just WebServer.
  • Renamed the WebServer.webSocketConnectionManager library to just WebSocketConnectionManager.
  • Added tons more docs, comments, and inline code examples; published Docs online using Jennex as the host and placed the link in the Pubspec.
  • Implemented the URI Object to make relative file path resolution more accurate.
  • Possibly solved issue that appears on Windows when resolving relative paths in serveVirtualDirectory() and serverStaticFile().
  • Added better honoring of the shouldBeVerbose parameter and changed to static property [breaking API change].
  • UTF8 encoding was required for files to be read before, but now it will work with any encoding and convert it to UTF8 during file read.

v1.0.9 (4.16.2015)

  • Added a new example for creating virtual directories at "example/virtual_directory.dart".
  • Removed some logging that may have been misleading.
  • Using a relative sub-directory path in serveVirtualDirectory() could lead to incorrect path following if the developer did not execute their script from the terminal in the project's root directory (such as using an Editor where it goes from the SDK's bin/ folder); fixed this by building an absolute directory path using Platform.script.path and getting the parent folder for the main execution, then building the relative path from there; this will prevent a lot of potential confusion for future developers using this Dart package; also added this to serveStaticFile().
  • Improved some of the comments and code in the example files.
  • Added an option to switch off recursive indexing in serveVirtualDirectory().

v1.0.8 (4.15.2015)

  • Added the ApiResponse and ApiErrorResponse classes to help make sending API data easier and with consistent formatting.
  • Updated the "example/web_server.dart" file to show uses of the new ApiResponse class.

v1.0.7 (4.15.2015)

  • Added built-in support for basic authentication path registering.
  • Code clean-up and DRY clean-up.
  • Basic security improvements.
  • New public helper methods for returning error pages.
  • Helper function for changing "{{...}}" variables in a text file using a key/value Map.
  • Updated some namespacing of the libraries.
  • (Again) Cleaned-up some files by removing redundant sub-files with the same name as the library (e.g. "lib/src/web_server/web_server.dart" -> "lib/src/web_server.dart" - already existed to include the sub-file by the same name).
  • Initial GitHub package commit!!!

v1.0.6 (4.11.2015)

  • Cleaned-up some files by removing redundant sub-files with the same name as the library (e.g. "lib/src/web_server/web_server.dart" -> "lib/src/web_server.dart" - already existed to include the sub-file by the same name).
  • Added locking of only certain methods, such as 'GET' or 'POST', at the WebServer level, otherwise, a 403 FORBIDDEN status code will be returned.
  • Put some limits in for blocking attempts at overloading the server with certain data in an attack.

v1.0.5 (4.2.2015)

  • Enabled GZIP compression - jeez was that an excellent discovery and improvement!!
  • Added a serveVirtualDirectory method.

v1.0.4 (late 2014-early 2015)

  • Created a folder with examples for how to use the web server.
  • Removed access to .on[] for the HttpServerHandler in favor of using .registerUrl().
  • An error will be thrown when attempting to create a secure server until the API is completed for that feature.
  • Renamed .registerUrl() to .registerFile().
  • Added .registerDirectory() to allow for manual handling of all immediate sub-items in a directory by a single event.

v1.0.3 (12.16.2014)

  • Original improvements and creation brought over from another of my projects; development that started back in June 2014.
  • Structure for creating servers bound securely using a security certificate (still not sure how to get this fully working, though).

Use this package as an executable

1. Install it

You can install the package from the command line:


$ pub global activate web_server

2. Use it

The package has the following executables:


$ web_server

Use this package as a library

1. Depend on it

Add this to your package's pubspec.yaml file:


dependencies:
  web_server: ^2.0.0

2. Install it

You can install packages from the command line:

with pub:


$ pub get

Alternatively, your editor might support pub get. Check the docs for your editor to learn more.

3. Import it

Now in your Dart code, you can use:


import 'package:web_server/web_server.dart';
  
Version Uploaded Documentation Archive
2.0.0+3 Mar 6, 2016 Go to the documentation of web_server 2.0.0+3 Download web_server 2.0.0+3 archive
2.0.0+2 Jan 22, 2016 Go to the documentation of web_server 2.0.0+2 Download web_server 2.0.0+2 archive
2.0.0+1 Dec 23, 2015 Go to the documentation of web_server 2.0.0+1 Download web_server 2.0.0+1 archive
2.0.0 Dec 21, 2015 Go to the documentation of web_server 2.0.0 Download web_server 2.0.0 archive
Popularity:
Describes how popular the package is relative to other packages. [more]
--
Health:
Code health derived from static analysis. [more]
--
Maintenance:
Reflects how tidy and up-to-date the package is. [more]
--
Overall:
Weighted score of the above. [more]
--
Learn more about scoring.

This package version is not analyzed, because it is more than two years old. Check the latest stable version for its analysis.

Dependencies

Package Constraint Resolved Available
Direct dependencies
Dart SDK >=1.9.0 <2.0.0