diff --git a/HttpBins/HttpServer.dll b/HttpBins/HttpServer.dll
new file mode 100644
index 00000000..bf543068
Binary files /dev/null and b/HttpBins/HttpServer.dll differ
diff --git a/HttpBins/HttpServer.pdb b/HttpBins/HttpServer.pdb
new file mode 100644
index 00000000..f1cfd83f
Binary files /dev/null and b/HttpBins/HttpServer.pdb differ
diff --git a/HttpBins/HttpServer.xml b/HttpBins/HttpServer.xml
new file mode 100644
index 00000000..fff737b5
--- /dev/null
+++ b/HttpBins/HttpServer.xml
@@ -0,0 +1,6183 @@
+
+
+
+ HttpServer
+
+
+
+
+ Used to read from a string object.
+
+
+
+
+ Base interface to read string tokens from different sources.
+
+
+
+
+ Assign a new buffer
+
+ Buffer to process.
+ Where to start process buffer
+ Buffer length
+
+
+
+ Assign a new buffer
+
+ Buffer to process
+
+
+
+ Consume current character.
+
+
+
+
+ Consume specified characters
+
+ One or more characters.
+
+
+
+ Consumes horizontal white spaces (space and tab).
+
+
+
+
+ Consume horizontal white spaces and the specified character.
+
+ Extra character to consume
+
+
+
+ Checks if one of the remaining bytes are a specified character.
+
+ Character to find.
+ true if found; otherwise false.
+
+
+
+ Read a character.
+
+ Character if not EOF; otherwise null.
+
+
+
+ Get a text line.
+
+
+ Will merge multiline headers.
+
+
+
+ Read quoted string
+
+ string if current character (in buffer) is a quote; otherwise null.
+
+
+
+ Read until end of string, or to one of the delimiters are found.
+
+ characters to stop at
+ A string (can be ).
+
+ Will not consume the delimiter.
+
+
+
+
+ Read until end of string, or to one of the delimiters are found.
+
+ A string (can be ).
+
+ Will not consume the delimiter.
+
+
+
+
+ Read to end of buffer, or until specified delimiter is found.
+
+ Delimiter to find.
+ A string (can be ).
+
+ Will not consume the delimiter.
+
+
+
+
+ Will read until specified delimiter is found.
+
+ Character to stop at.
+ A string if the delimiter was found; otherwise null.
+
+ Will trim away spaces and tabs from the end.
+ Will not consume the delimiter.
+
+
+
+
+ Read until one of the delimiters are found.
+
+ characters to stop at
+ A string if one of the delimiters was found; otherwise null.
+
+ Will trim away spaces and tabs from the end.
+ Will not consume the delimiter.
+
+
+
+
+ Read until a horizontal white space occurs.
+
+ A string if a white space was found; otherwise null.
+
+
+
+ Gets current character
+
+ if end of buffer.
+
+
+
+ Gets if end of buffer have been reached
+
+
+
+
+ Gets if more bytes can be processed.
+
+
+
+
+ Gets or sets current position in buffer.
+
+
+ THINK before you manually change the position since it can blow up
+ the whole parsing in your face.
+
+
+
+
+ Gets total length of buffer.
+
+
+
+
+ Gets or sets line number.
+
+
+
+
+ Gets next character
+
+ if end of buffer.
+
+
+
+ Gets number of bytes left.
+
+
+
+
+ Initializes a new instance of the class.
+
+ Buffer to process.
+
+
+
+ Initializes a new instance of the class.
+
+
+
+
+ Assign a new buffer
+
+ Buffer to process.
+ Where to start process buffer
+ Buffer length
+ MUST be of type .
+ buffer needs to be of type string
+
+
+
+ Assign a new buffer
+
+ Buffer to process
+ MUST be of type .
+ buffer needs to be of type string
+
+
+
+ Consume current character.
+
+
+
+
+ Get a text line.
+
+
+ Will merge multiline headers.
+
+
+
+ Read quoted string
+
+ string if current character (in buffer) is a quote; otherwise null.
+
+
+
+ Read until end of string, or to one of the delimiters are found.
+
+ characters to stop at
+ A string (can be ).
+ InvalidOperationException.
+
+
+
+ Read until end of string, or to one of the delimiters are found.
+
+ A string (can be ).
+
+ Will not consume the delimiter.
+
+
+
+
+ Read to end of buffer, or until specified delimiter is found.
+
+ Delimiter to find.
+ A string (can be ).
+ InvalidOperationException.
+
+
+
+ Consume specified characters
+
+ One or more characters.
+
+
+
+ Consumes horizontal white spaces (space and tab).
+
+
+
+
+ Read a character.
+
+
+ Character if not EOF; otherwise null.
+
+
+
+
+ Will read until specified delimiter is found.
+
+ Character to stop at.
+
+ A string if the delimiter was found; otherwise null.
+
+
+ Will trim away spaces and tabs from the end.
+ Will not consume the delimiter.
+
+ InvalidOperationException.
+
+
+
+ Read until one of the delimiters are found.
+
+ characters to stop at
+
+ A string if one of the delimiters was found; otherwise null.
+
+
+ Will not consume the delimiter.
+
+ InvalidOperationException.
+
+
+
+ Read until a horizontal white space occurs (or end, or end of line).
+
+
+ A string if a white space was found; otherwise null.
+
+
+
+
+ Consume horizontal white spaces and the specified character.
+
+ Extra character to consume
+
+
+
+ Checks if one of the remaining bytes are a specified character.
+
+ Character to find.
+
+ true if found; otherwise false.
+
+
+
+
+ Gets or sets line number.
+
+
+
+
+ Gets if end of buffer have been reached
+
+
+
+
+
+ Gets if more bytes can be processed.
+
+
+
+
+
+ Gets next character
+
+ if end of buffer.
+
+
+
+ Gets current character
+
+ if end of buffer.
+
+
+
+ Gets or sets current position in buffer.
+
+
+ THINK before you manually change the position since it can blow up
+ the whole parsing in your face.
+
+
+
+
+ Gets total length of buffer.
+
+
+
+
+
+ Gets number of bytes left.
+
+
+
+
+ Reads strings from a byte array.
+
+
+
+
+ Initializes a new instance of the class.
+
+
+
+
+ Initializes a new instance of the class.
+
+ Encoding to use when converting byte array to strings.
+
+
+
+ Initializes a new instance of the class.
+
+ Buffer to read from.
+ Encoding to use when converting byte array to strings.
+
+
+
+ Assign a new buffer
+
+ Buffer to process.
+ Where to start process buffer
+ Buffer length
+ Buffer needs to be a byte array
+
+
+
+ Assign a new buffer
+
+ Buffer to process
+ Buffer needs to be a byte array
+
+
+
+ Consume current character.
+
+
+
+
+ Get a text line.
+
+
+ Will merge multi line headers.
+
+
+
+ Read quoted string
+
+ string if current character (in buffer) is a quote; otherwise null.
+
+
+
+ Read until end of string, or to one of the delimiters are found.
+
+ characters to stop at
+
+ A string (can be ).
+
+
+ Will not consume the delimiter.
+
+ InvalidOperationException.
+
+
+
+ Read until end of string, or to one of the delimiters are found.
+
+ A string (can be ).
+
+ Will not consume the delimiter.
+
+
+
+
+ Read to end of buffer, or until specified delimiter is found.
+
+ Delimiter to find.
+
+ A string (can be ).
+
+
+ Will not consume the delimiter.
+
+ InvalidOperationException.
+
+
+
+ Consume specified characters
+
+ One or more characters.
+
+
+
+ Consumes horizontal white spaces (space and tab).
+
+
+
+
+ Consume horizontal white spaces and the specified character.
+
+ Extra character to consume
+
+
+
+ Read a character.
+
+
+ Character if not EOF; otherwise null.
+
+
+
+
+ Will read until specified delimiter is found.
+
+ Character to stop at.
+
+ A string if the delimiter was found; otherwise null.
+
+
+ Will trim away spaces and tabs from the end.
+ InvalidOperationException.
+
+
+
+ Read until one of the delimiters are found.
+
+ characters to stop at
+
+ A string if one of the delimiters was found; otherwise null.
+
+
+ Will not consume the delimiter.
+
+ InvalidOperationException.
+
+
+
+ Read until a horizontal white space occurs.
+
+ A string if a white space was found; otherwise null.
+
+
+
+ Checks if one of the remaining bytes are a specified character.
+
+ Character to find.
+
+ true if found; otherwise false.
+
+
+
+
+ Gets or sets line number.
+
+
+
+
+ Gets if end of buffer have been reached
+
+
+
+
+
+ Gets if more bytes can be processed.
+
+
+
+
+
+ Gets next character
+
+ if end of buffer.
+
+
+
+ Gets current character
+
+ if end of buffer.
+
+
+
+ Gets or sets current position in buffer.
+
+
+ THINK before you manually change the position since it can blow up
+ the whole parsing in your face.
+
+
+
+
+ Gets total length of buffer.
+
+
+
+
+
+ Gets number of bytes left.
+
+
+
+
+ Event arguments used when a new header have been parsed.
+
+
+
+
+ Initializes a new instance of the class.
+
+ Name of header.
+ Header value.
+ Name cannot be empty
+ value is null.
+
+
+
+ Initializes a new instance of the class.
+
+
+
+
+ Gets or sets header name.
+
+
+
+
+ Gets or sets header value.
+
+
+
+
+ Resource information.
+
+
+ Used by content providers to be able to get information
+ on resources (views, files etc).
+
+
+
+
+ Gets or sets date when resource was modified.
+
+
+ if not used.
+
+
+ Should always be universal time.
+
+
+
+
+ Gets or sets resource stream.
+
+
+
+
+ Loads resources from a specific location (such as assembly, hard drive etc).
+
+
+
+
+ Checks if a resource exists in the specified directory
+
+ Uri path to resource
+ true if resource was found; otherwise false.
+
+
+ if (resources.Exists("/files/user/user.png"))
+ Debug.WriteLine("Resource exists.");
+
+
+
+
+
+ Find all views in a folder/path.
+
+ Absolute Uri path to files that should be found, can end with wild card.
+ Collection to add all view names to.
+
+
+
+ Gets a resource.
+
+ Uri path to resource.
+ Resource
+ Uri contains forbidden characters.
+
+
+ Resource resource = resources.Get("/files/user/user.png");
+
+
+
+
+
+ Parses Cookie header.
+
+
+
+
+ Used to parse header values
+
+
+
+
+ Parse a header
+
+ Name of header.
+ Reader containing value.
+ HTTP Header
+ Header value is not of the expected format.
+
+
+
+ Parse a header
+
+ Name of header.
+ Reader containing value.
+ HTTP Header
+ Header value is not of the expected format.
+
+
+
+ Used by to filter out unwanted connections.
+
+
+
+
+ Initializes a new instance of the class.
+
+ The socket.
+
+
+
+ Gets or sets if socket can be accepted.
+
+
+
+
+ Gets socket.
+
+
+
+
+ Http listener
+
+
+
+
+ Start listener.
+
+ Number of pending accepts.
+
+ Make sure that you are subscribing on first.
+
+ Listener have already been started.
+ Failed to start socket.
+ Invalid port number.
+
+
+
+ Stop listener.
+
+
+
+
+ Gets listener address.
+
+
+
+
+ Gets if listener is secure.
+
+
+
+
+ Gets if listener have been started.
+
+
+
+
+ Gets or sets logger.
+
+
+
+
+ Gets listening port.
+
+
+
+
+ Gets the maximum content size.
+
+ The content length limit.
+
+ Used when responding to 100-continue.
+
+
+
+
+ A new request have been received.
+
+
+
+
+ Can be used to reject certain clients.
+
+
+
+
+ A HTTP exception have been thrown.
+
+
+ Fill the body with a user friendly error page, or redirect to somewhere else.
+
+
+
+
+ Collection of files.
+
+
+
+
+ Checks if a file exists.
+
+ Name of the file (form item name)
+
+
+
+
+ Add a new file.
+
+ File to add.
+
+
+
+ Remove all files from disk.
+
+
+
+
+ Get a file
+
+ Name in form
+ File if found; otherwise null.
+
+
+
+ Gets number of files
+
+
+
+
+ Custom network stream to mark sockets as reusable when disposing the stream.
+
+
+
+
+ Creates a new instance of the class for the specified .
+
+
+ The that the will use to send and receive data.
+
+
+ The parameter is null.
+
+
+ The parameter is not connected.
+ -or-
+ The property of the parameter is not .
+ -or-
+ The parameter is in a nonblocking state.
+
+
+
+
+ Initializes a new instance of the class for the specified with the specified ownership.
+
+
+ The that the will use to send and receive data.
+
+
+ Set to true to indicate that the will take ownership of the ; otherwise, false.
+
+
+ The parameter is null.
+
+
+ The parameter is not connected.
+ -or-
+ the value of the property of the parameter is not .
+ -or-
+ the parameter is in a nonblocking state.
+
+
+
+
+ Creates a new instance of the class for the specified with the specified access rights.
+
+
+ The that the will use to send and receive data.
+
+
+ A bitwise combination of the values that specify the type of access given to the over the provided .
+
+
+ The parameter is null.
+
+
+ The parameter is not connected.
+ -or-
+ the property of the parameter is not .
+ -or-
+ the parameter is in a nonblocking state.
+
+
+
+
+ Creates a new instance of the class for the specified with the specified access rights and the specified ownership.
+
+
+ The that the will use to send and receive data.
+
+
+ A bitwise combination of the values that specifies the type of access given to the over the provided .
+
+
+ Set to true to indicate that the will take ownership of the ; otherwise, false.
+
+
+ The parameter is null.
+
+
+ The parameter is not connected.
+ -or-
+ The property of the parameter is not .
+ -or-
+ The parameter is in a nonblocking state.
+
+
+
+
+ Closes the current stream and releases any resources (such as sockets and file handles) associated with the current stream.
+
+
+
+
+ Releases the unmanaged resources used by the and optionally releases the managed resources.
+
+ true to release both managed and unmanaged resources; false to release only unmanaged resources.
+
+
+
+ Request sent to a HTTP server.
+
+
+
+
+
+ Base interface for request and response.
+
+
+
+
+ Add a new header.
+
+
+
+
+
+
+ Add a new header.
+
+ Header to add.
+
+
+
+ Gets body stream.
+
+
+
+
+ Size of the body. MUST be specified before sending the header,
+ unless property Chunked is set to true.
+
+
+
+
+ Kind of content in the body
+
+ Default is text/html
+
+
+
+ Gets or sets encoding
+
+
+
+
+ Gets headers.
+
+
+
+
+ Get a header
+
+ Type that it should be cast to
+ Name of header
+ Header if found and casted properly; otherwise null.
+
+
+
+ Gets or sets connection header.
+
+
+
+
+ Gets cookies.
+
+
+
+
+ Gets all uploaded files.
+
+
+
+
+ Gets form parameters.
+
+
+
+
+ Gets or sets HTTP version.
+
+
+
+
+ Gets if request is an Ajax request.
+
+
+
+
+ Gets or sets HTTP method.
+
+
+
+
+ Gets query string and form parameters
+
+
+
+
+ Gets query string.
+
+
+
+
+ Gets requested URI.
+
+
+
+
+ Serves files in the web server.
+
+
+
+ FileModule fileModule = new FileModule();
+ fileModule.Resources.Add(new FileResources("/", "C:\\inetpub\\myweb"));
+
+
+
+
+
+ HTTP Module
+
+
+
+
+ Process a request.
+
+ Request information
+ What to do next.
+
+
+
+ Initializes a new instance of the class.
+
+ baseUri or basePath is null.
+
+
+
+ Mime types that this class can handle per default
+
+
+ Contains the following mime types:
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Will send a file to client.
+
+ HTTP context containing outbound stream.
+ Response containing headers.
+ File stream
+
+
+
+ Process a request.
+
+ Request information
+ What to do next.
+ Failed to find file extension
+ Forbidden file type.
+
+
+
+ Gets a list with all allowed content types.
+
+ All other mime types will result in .
+
+
+
+ Gets provider used to add files to the file manager,
+
+
+
+
+ An exception that can't be handled by the library have been thrown.
+
+
+
+
+ Initializes a new instance of the class.
+
+ The exception.
+
+
+
+ Gets caught exception.
+
+
+
+
+ Helper for content types.
+
+
+
+
+ Decodes forms that have multiple sections.
+
+
+ http://www.faqs.org/rfcs/rfc1867.html
+
+
+
+
+ Decodes body stream.
+
+
+
+
+ Decode body stream
+
+ Stream containing the content
+ Content type header
+ Stream encoding
+ Decoded data.
+ Body format is invalid for the specified content type.
+ Something unexpected failed.
+
+
+
+ All content types that the decoder can parse.
+
+ A collection of all content types that the decoder can handle.
+
+
+
+ form-data
+
+
+
+
+ multipart/form-data
+
+
+
+
+ Decode body stream
+
+ Stream containing the content
+ Content type header
+ Stream encoding
+ Decoded data.
+ Body format is invalid for the specified content type.
+ Something unexpected failed.
+ stream is null.
+
+
+
+ All content types that the decoder can parse.
+
+ A collection of all content types that the decoder can handle.
+
+
+
+ A HTTP parser using delegates to which parsing methods.
+
+
+
+
+ Initializes a new instance of the class.
+
+
+
+
+ Parser method to copy all body bytes.
+
+
+ Needed since a TCP packet can contain multiple messages
+ after each other, or partial messages.
+
+
+
+ Try to find a header name.
+
+
+
+
+
+ Get header values.
+
+
+ Will also look for multi header values and automatically merge them to one line.
+ Content length is not a number.
+
+
+
+ Toggle body bytes event.
+
+
+
+
+
+
+
+ Raise the event, since we have successfully parsed a message and it's body.
+
+
+
+
+ First message line.
+
+ Will always contain three elements.
+ Used to raise the or event
+ depending on the words in the array.
+ BadRequestException.
+
+
+
+ Continue parsing a message
+
+ Byte buffer containing bytes
+ Where to start the parsing
+ Number of bytes to parse
+ index where the parsing stopped.
+ Parsing failed.
+
+
+
+ Parses the first line in a request/response.
+
+ true if first line is well formatted; otherwise false.
+ Invalid request/response line.
+
+
+
+ Reset parser to initial state.
+
+
+
+
+ Gets or sets current line number.
+
+
+
+
+ The request line has been parsed.
+
+
+
+
+ Response line has been parsed.
+
+
+
+
+ Parsed a header.
+
+
+
+
+ Received body bytes.
+
+
+
+
+ A message have been successfully parsed.
+
+
+
+
+ Used to be able to quickly swap parser method.
+
+
+
+
+
+ Default log filter implementation.
+
+
+
+
+ Determines which classes can log
+
+
+
+
+ Checks if the specified type can send
+ log entries at the specified level.
+
+ Log level
+ Type that want to write a log entry.
+ true if logging is allowed; otherwise false.
+
+
+
+ Add a name space filter.
+
+ Name space to add filter for.
+ Minimum log level required.
+
+
+ // Parsing can only add error and fatal messages
+ AddNamespace("SipSharp.Messages.Headers.Parsers", LogLevel.Error);
+ AddType(typeof(SipParser), LogLevel.Error);
+
+ // Transport layer can only log warnings, errors and fatal messages
+ AddNamespace("SipSharp.Transports.*", LogLevel.Warning);
+
+
+
+
+
+ Used to specify standard filter rules
+
+
+ Parser can only display errors. Transports only warnings.
+
+
+
+
+ Add filter for a type
+
+ Type to add filter for.
+ Minimum log level required.
+
+
+ // Parsing can only add error and fatal messages
+ AddNamespace("SipSharp.Messages.Headers.Parsers", LogLevel.Error);
+ AddType(typeof(SipParser), LogLevel.Error);
+
+ // Transport layer can only log warnings, errors and fatal messages
+ AddNamespace("SipSharp.Transports.*", LogLevel.Warning);
+
+
+
+
+
+ Add filter for a type
+
+ Type to add filter for.
+ Minimum log level required.
+
+
+ // Parsing can only add error and fatal messages
+ AddNamespace("SipSharp.Messages.Headers.Parsers", LogLevel.Error);
+ AddType("SipSharp.Messages.MessageFactory", LogLevel.Error);
+
+ // Transport layer can only log warnings, errors and fatal messages
+ AddNamespace("SipSharp.Transports.*", LogLevel.Warning);
+
+
+ Type could not be identified.
+
+
+
+ Checks if the specified type can send
+ log entries at the specified level.
+
+ Log level
+ Type that want to write a log entry.
+ true if logging is allowed; otherwise false.
+
+
+ No filters = everything logged. = no logs. Don't use a rule with '*' or '.*'
+
+
+
+ User have specified a wild card filter.
+
+
+ Wild card filters are used to log a name space and
+ all it's children name spaces.
+
+
+
+
+ Factory implementation used to create logs.
+
+
+
+
+ Create a new logger.
+
+ Type that requested a logger.
+ Logger for the specified type;
+
+ MUST ALWAYS return a logger. Return if no logging
+ should be used.
+
+
+
+
+ Response to a request.
+
+
+
+
+ Redirect user.
+
+ Where to redirect to.
+
+ Any modifications after a redirect will be ignored.
+
+
+
+
+ Gets connection type.
+
+
+
+
+ Gets cookies.
+
+
+
+
+ Gets HTTP version.
+
+
+ Default is HTTP/1.1
+
+
+
+
+ Information about why a specific status code was used.
+
+
+
+
+ Status code that is sent to the client.
+
+ Default is
+
+
+
+ Gets or sets content type
+
+
+
+
+ Rules are used to perform operations before a request is being handled.
+ Rules can be used to create routing etc.
+
+
+
+
+ Process the incoming request.
+
+ Request context information.
+ Processing result.
+ If any parameter is null.
+
+
+
+ Used to access resources.
+
+
+
+
+ Add a new resource loader.
+
+ Provider to add.
+ Manager have been started.
+
+
+
+ Check if a resource exists.
+
+ Uri to check
+ true if found; otherwise false.
+
+
+ if (manager.Exists("/views/user/view.haml"))
+ return true
+
+
+
+
+
+ Get a resource.
+
+ Uri path to resource.
+ Resource if found; otherwise null.
+
+
+ Resource resource = manager.Get("/views/user/view.haml");
+
+
+
+
+
+ Start manager.
+
+
+
+
+ Gets number of resource providers
+
+
+
+
+ Parses "Date" header.
+
+
+
+
+ Parse a header
+
+ Name of header.
+ Reader containing value.
+ HTTP Header
+ Header value is not of the expected format.
+
+
+
+ Content-type
+
+
+
+
+ Header in a message
+
+
+ Important! Each header should override ToString()
+ and return it's data correctly formatted as a HTTP header value.
+
+
+
+
+ Gets header name
+
+
+
+
+ Gets value as it would be sent back to client.
+
+
+
+
+ Header name.
+
+
+
+
+ Initializes a new instance of the class.
+
+ Type of the content.
+ Value parameters.
+
+
+
+ Initializes a new instance of the class.
+
+ Type of the content.
+
+
+
+ Returns data formatted as a HTTP header value.
+
+
+ A that represents the current .
+
+
+
+
+ Gets all parameters.
+
+
+
+
+ Gets content type.
+
+
+
+
+ Gets header name
+
+
+
+
+ Used to get or set properties on objects.
+
+
+ This class should be a bit faster than the standard reflection.
+
+
+
+
+ Get cached type.
+
+ Type to get/set properties in
+ Type to use
+
+
+
+ Flyweight design pattern implementation.
+
+ Type of object.
+
+
+
+ Initializes a new instance of the class.
+
+ How large buffers to allocate.
+
+
+
+ Get an object.
+
+ Created object.
+ Will create one if queue is empty.
+
+
+
+ Enqueues the specified buffer.
+
+ Object to enqueue.
+ Buffer is is less than the minimum requirement.
+
+
+
+ Used to create new objects.
+
+ Type of objects to create.
+ Newly created object.
+ .
+
+
+
+ Used to load/store sessions in the server.
+
+
+
+
+ Initializes a new instance of the class.
+
+ Web server that the provider is for..
+ Store to use.
+
+
+
+ Initializes a new instance of the class.
+
+ The server.
+
+ Uses a file store.
+
+
+
+
+ Loads a session for all requests that got the session cookie.
+
+ The sender.
+ The instance containing the event data.
+
+
+
+ Gets current session
+
+ Session if set, otherwise null.
+
+
+
+ Gets or sets the session life time in minutes.
+
+ The session life time.
+
+
+
+ A session have been loaded. Use to access it.
+
+
+
+
+ Used to build headers.
+
+
+
+
+ Add a parser
+
+ Header that the parser is for.
+ Parser implementation
+
+ Will replace any existing parser for the specified header.
+
+
+
+
+ Add all default (built-in) parsers.
+
+
+ Will not replace previously added parsers.
+
+
+
+
+ Create a header parser
+
+ implementation.
+
+
+ Uses attribute to find which headers
+ the parser is for.
+
+ Will not replace previously added parsers.
+
+
+
+
+ Parse a header.
+
+ Name of header
+ Header value
+ Header.
+ Value is not a well formatted header value.
+
+
+
+ Arguments used when more body bytes have come.
+
+
+
+
+ Initializes a new instance of the class.
+
+ buffer that contains the received bytes.
+ offset in buffer where to start processing.
+ number of bytes from that should be parsed.
+ buffer is null.
+
+
+
+ Initializes a new instance of the class.
+
+
+
+
+ Gets or sets buffer that contains the received bytes.
+
+
+
+
+ Gets or sets number of bytes from that should be parsed.
+
+
+
+
+ Gets or sets offset in buffer where to start processing.
+
+
+
+
+ redirects from one URL to another.
+
+
+
+
+ Initializes a new instance of the class.
+
+ Absolute path (no server name)
+ Absolute path (no server name)
+
+ server.Add(new RedirectRule("/", "/user/index"));
+
+
+
+
+ Initializes a new instance of the class.
+
+ Absolute path (no server name)
+ Absolute path (no server name)
+ true if request should be redirected, false if the request URI should be replaced.
+
+ server.Add(new RedirectRule("/", "/user/index"));
+
+
+
+
+ Process the incoming request.
+
+ Request context.
+ Processing result.
+ If any parameter is null.
+
+
+
+ Gets string to match request URI with.
+
+ Is compared to request.Uri.AbsolutePath
+
+
+
+ Gets whether the server should redirect the client instead of simply modifying the URI.
+
+
+ false means that the rule will replace
+ the current request URI with the new one from this class.
+ true means that a redirect response is sent to the client.
+
+
+
+
+ Gets where to redirect.
+
+
+
+
+ cookie sent by the client/browser
+
+
+
+
+
+ Constructor.
+
+ cookie identifier
+ cookie content
+ id or content is null
+ id is empty
+
+
+
+ Gets the cookie HTML representation.
+
+ cookie string
+
+
+
+ Gets the cookie identifier.
+
+
+
+
+ Gets value.
+
+
+ Set to null to remove cookie.
+
+
+
+
+ A request have been parsed successfully by the server.
+
+
+
+
+ Initializes a new instance of the class.
+
+ Received request.
+
+
+
+ Gets received request.
+
+
+
+
+ Context that received a HTTP request.
+
+
+
+
+ Disconnect context.
+
+
+
+
+ Gets if current context is using a secure connection.
+
+
+
+
+ Gets logger.
+
+
+
+
+ Gets remote end point
+
+
+
+
+ Gets stream used to send/receive data to/from remote end point.
+
+
+
+ The stream can be any type of stream, do not assume that it's a network
+ stream. For instance, it can be a or a ZipStream.
+
+
+
+
+
+ Gets the currently handled request
+
+ The request.
+
+
+
+ Gets the response that is going to be sent back
+
+ The response.
+
+
+
+ File sent from remote end.
+
+
+
+
+ Gets or sets content type.
+
+
+
+
+ Gets or sets name in form.
+
+
+
+
+ Gets or sets name original file name
+
+
+
+
+ Gets or sets filename for locally stored file.
+
+
+
+
+ Client X.509 certificate, X.509 chain, and any SSL policy errors encountered
+ during the SSL stream creation
+
+
+
+
+ Initializes a new instance of the class.
+
+ The certificate.
+ Client security certificate chain.
+ Any SSL policy errors encountered during the SSL stream creation.
+
+
+
+ Client security certificate
+
+
+
+
+ Client security certificate chain
+
+
+
+
+ Any SSL policy errors encountered during the SSL stream creation
+
+
+
+
+ Provides sessions.
+
+ Type of session object
+
+ Will always use files for sessions (utilizing the binary formatter), but can
+ also cache them in memory.
+
+ If caching is enabled, it will only write sessions to disk every 20 seconds if they have
+ been accessed the last minute (to not keep writing dead sessions to disk).
+
+
+
+
+
+ Initializes a new instance of the class.
+
+ Session type must use [Serializable] attribute.
+
+
+
+ Create a new session.
+
+
+
+
+
+ Load session
+
+ Id of session.
+ Session if found; otherwise null.
+ sessionId is null.
+
+
+
+ Load session when a new request comes in.
+
+
+
+
+
+
+ Save a session to disk.
+
+ Session to write to disk.
+
+ You are responsible for writing sessions to disk if you are not using caching.
+
+
+
+
+ Start the session system and hook
+
+
+
+
+
+ Stop session handling
+
+
+
+
+ Gets or sets session cookie name
+
+
+
+
+ Gets or sets cache
+
+
+
+
+ Gets current session.
+
+
+
+
+ Gets or sets number of seconds before a session expired.
+
+
+ A session have expired if nothing have accessed it for X seconds. This
+ class modifies the write time each time it's accessed.
+
+
+
+
+ Determines if cookie should be set in the response.
+
+
+
+
+ Invoked when a session have been changed and should be written to disc.
+
+
+
+
+ Base class for sessions.
+
+
+ Your class must be tagged with attribute to be able to use sessions.
+
+
+
+
+ The session have been changed and should be written to disk.
+
+
+
+
+ Session have been changed.
+
+
+
+
+ Gets or sets when session was accessed last
+
+
+
+
+ Gets current session.
+
+
+
+
+ Gets or sets session id.
+
+
+
+
+ Gets or sets when the session was last written to disk.
+
+
+
+
+ Used when the request line have been successfully parsed.
+
+
+
+
+ Initializes a new instance of the class.
+
+ The HTTP method.
+ The URI path.
+ The HTTP version.
+
+
+
+ Initializes a new instance of the class.
+
+
+
+
+ Gets or sets HTTP method.
+
+
+ Should be one of the methods declared in .
+
+
+
+
+ Gets or sets requested URI path.
+
+
+
+
+ Gets or sets the version of the SIP protocol that the client want to use.
+
+
+
+
+ cookie being sent back to the browser.
+
+
+
+
+
+ Constructor.
+
+ cookie identifier
+ cookie content
+ cookie expiration date. Use for session cookie.
+ id or content is null
+ id is empty
+
+
+
+ Create a new cookie
+
+ name identifying the cookie
+ cookie value
+ when the cookie expires. Setting will delete the cookie when the session is closed.
+ Path to where the cookie is valid
+ Domain that the cookie is valid for.
+
+
+
+ Create a new cookie
+
+ Name and value will be used
+ when the cookie expires.
+
+
+
+ Gets the cookie HTML representation.
+
+ cookie string
+
+
+
+ Gets when the cookie expires.
+
+ means that the cookie expires when the session do so.
+
+
+
+ Gets path that the cookie is valid under.
+
+
+
+
+ Used to define which headers a parse is for.
+
+
+
+
+ Initializes a new instance of the class.
+
+ Name of the header.
+
+
+
+ Gets name of header that this parser is for.
+
+
+
+
+ Collection of headers.
+
+
+
+
+ Gets a header
+
+ header name.
+ header if found; otherwise null.
+
+
+
+ Something failed during parsing.
+
+
+
+
+ Request couldn't be parsed successfully.
+
+
+
+
+ Exception thrown from HTTP server.
+
+
+
+
+ Initializes a new instance of the class.
+
+ HTTP status code.
+ Exception description.
+
+
+
+ Initializes a new instance of the class.
+
+ HTTP status code.
+ Exception description.
+ Inner exception.
+
+
+
+ Gets HTTP status code.
+
+
+
+
+ Initializes a new instance of the class.
+
+ Exception description.
+
+
+
+ Initializes a new instance of the class.
+
+ Exception description.
+ Exception description.
+
+
+
+ Initializes a new instance of the class.
+
+ Exception description.
+
+
+
+ Initializes a new instance of the class.
+
+ Exception description.
+ Inner exception.
+
+
+
+ Provides resources.
+
+
+
+
+ Get all view names from a folder.
+
+ Path to find views in.
+ A collection of view names (without path).
+
+
+
+ Add a new resource loader.
+
+ Provider to add.
+ Manager have been started.
+
+
+
+ Start manager.
+
+
+
+
+ Check if a resource exists.
+
+ Uri to check
+ true if found; otherwise false.
+
+
+ if (manager.Exists("/views/user/view.haml"))
+ return true
+
+
+
+
+
+ Get a resource.
+
+ Uri path to resource.
+ Resource if found; otherwise null.
+
+
+ Resource resource = manager.Get("/views/user/view.haml");
+
+
+
+
+
+ Gets number of resource providers
+
+
+
+
+ Collection of parameters.
+
+
+ or is not used since each parameter can
+ have multiple values.
+
+
+
+
+ Collection of parameters
+
+
+
+
+ Get a parameter.
+
+
+
+
+
+
+ Add a query string parameter.
+
+ Parameter name
+ Value
+
+
+
+ Checks if the specified parameter exists
+
+ Parameter name.
+ true if found; otherwise false;
+
+
+
+ Gets number of parameters.
+
+
+
+
+ Gets last value of an parameter.
+
+ Parameter name
+ String if found; otherwise null.
+
+
+
+ Initializes a new instance of the class.
+
+ Collections to merge.
+
+ Later collections will overwrite parameters from earlier collections.
+
+
+
+
+ Initializes a new instance of the class.
+
+
+
+
+ Get a list of string arrays.
+
+
+
+
+
+ Get parameters
+
+ Sub array (text array)
+
+
+
+
+ Returns an enumerator that iterates through the collection.
+
+
+ A that can be used to iterate through the collection.
+
+ 1
+
+
+
+ Returns an enumerator that iterates through a collection.
+
+
+ An object that can be used to iterate through the collection.
+
+ 2
+
+
+
+ Get a parameter.
+
+
+
+
+
+
+ Add a query string parameter.
+
+ Parameter name
+ Value
+
+
+
+ Checks if the specified parameter exists
+
+ Parameter name.
+ true if found; otherwise false;
+
+
+
+ Gets number of parameters.
+
+
+
+
+ Gets last value of an parameter.
+
+ Parameter name
+ String if found; otherwise null.
+
+
+
+ Result of processing.
+
+
+
+
+ Continue with the next handler
+
+
+
+
+ No more handlers can process the request.
+
+
+ The server will process the response object and
+ generate a HTTP response from it.
+
+
+
+
+ Response have been sent back by the handler.
+
+
+ This option should only be used if you are streaming
+ something or sending back a custom result. The server will
+ not process the response object or send anything back
+ to the client.
+
+
+
+
+ A HTTP context
+
+
+
+
+
+
+
+ Initializes a new instance of the class.
+
+ Socket received from HTTP listener.
+ Context used to parse incoming messages.
+
+
+
+ Performs application-defined tasks associated with freeing, releasing, or resetting unmanaged resources.
+
+ 2
+
+
+
+ Disconnect context.
+
+
+
+
+ Close and release socket.
+
+
+
+
+ Create stream used to send and receive bytes from the socket.
+
+ Socket to wrap
+ Stream
+ Stream could not be created.
+
+
+
+ Interpret incoming data.
+
+
+
+
+
+ A request was received from the parser.
+
+
+
+
+
+
+ Parse all complete requests in buffer.
+
+
+ offset in buffer where parsing stopped.
+ Parsing failed.
+
+
+
+ Start content.
+
+ A socket operation failed.
+ Reading from stream failed.
+
+
+
+ Gets currently executing HTTP context.
+
+
+
+
+ Gets or sets description
+
+
+
+
+ gets factory used to build request objects
+
+
+
+
+ Gets socket
+
+
+
+
+ Gets remove end point
+
+
+
+
+ Gets network stream.
+
+
+
+
+ Gets the currently handled request
+
+ The request.
+
+
+
+ Gets the response that is going to be sent back
+
+ The response.
+
+
+
+ Gets logger.
+
+
+
+
+ Gets if current context is using a secure connection.
+
+
+
+
+ Triggered for all requests in the server (after the response have been sent)
+
+
+
+
+ Triggered for current request (after the response have been sent)
+
+
+
+
+ A new request have been received.
+
+
+
+
+ A new request have been received (invoked for ALL requests)
+
+
+
+
+ Client have been disconnected.
+
+
+
+
+ Client asks if he may continue.
+
+
+ If the body is too large or anything like that you should respond .
+
+
+
+
+ Used to store all headers that that aren't recognized.
+
+
+
+
+ Initializes a new instance of the class.
+
+ The name.
+ The value.
+
+
+
+ Gets or sets value
+
+
+
+
+ Gets header name
+
+
+
+
+ The Connection general-header field allows the sender to specify options
+ that are desired for that particular connection and MUST NOT be
+ communicated by proxies over further connections.
+
+
+
+ HTTP/1.1 proxies MUST parse the Connection header field before a
+ message is forwarded and, for each connection-token in this field,
+ remove any header field(s) from the message with the same name as the
+ connection-token. Connection options are signaled by the presence of
+ a connection-token in the Connection header field, not by any
+ corresponding additional header field(s), since the additional header
+ field may not be sent if there are no parameters associated with that
+ connection option.
+
+ Message headers listed in the Connection header MUST NOT include
+ end-to-end headers, such as Cache-Control.
+
+ HTTP/1.1 defines the "close" connection option for the sender to
+ signal that the connection will be closed after completion of the
+ response. For example,
+
+ Connection: close
+
+ in either the request or the response header fields indicates that
+ the connection SHOULD NOT be considered `persistent' (section 8.1)
+ after the current request/response is complete.
+
+ HTTP/1.1 applications that do not support persistent connections MUST
+ include the "close" connection option in every message.
+
+ A system receiving an HTTP/1.0 (or lower-version) message that
+ includes a Connection header MUST, for each connection-token in this
+ field, remove and ignore any header field(s) from the message with
+ the same name as the connection-token. This protects against mistaken
+ forwarding of such header fields by pre-HTTP/1.1 proxies. See section
+ 19.6.2 in RFC2616.
+
+
+
+
+
+ Header name
+
+
+
+
+ Default connection header for HTTP/1.0
+
+
+
+
+ Default connection header for HTTP/1.1
+
+
+
+
+ Initializes a new instance of the class.
+
+ Connection type.
+ The parameters.
+
+
+
+ Initializes a new instance of the class.
+
+ The type.
+
+
+
+ Returns data formatted as a HTTP header value.
+
+
+ A that represents the current .
+
+
+
+
+ Gets connection parameters.
+
+
+
+
+ Gets or sets connection type
+
+
+
+
+ Gets header name
+
+
+
+
+ Type of HTTP connection
+
+
+
+
+ Connection is closed after each request-response
+
+
+
+
+ Connection is kept alive for X seconds (unless another request have been made)
+
+
+
+
+ Parameter in
+
+
+
+
+ Gets *last* value.
+
+
+ Parameters can have multiple values. This property will always get the last value in the list.
+
+ String if any value exist; otherwise null.
+
+
+
+ Gets or sets name.
+
+
+
+
+ Gets a list of all values.
+
+
+
+
+ A parameter in .
+
+
+
+
+ Returns an enumerator that iterates through the collection.
+
+
+ A that can be used to iterate through the collection.
+
+ 1
+
+
+
+ Returns an enumerator that iterates through a collection.
+
+
+ An object that can be used to iterate through the collection.
+
+ 2
+
+
+
+ Gets last value.
+
+
+ Parameters can have multiple values. This property will always get the last value in the list.
+
+ String if any value exist; otherwise null.
+
+
+
+ Gets or sets name.
+
+
+
+
+ Gets a list of all values.
+
+
+
+
+ Secure version of the HTTP listener.
+
+
+
+
+ Http listener.
+
+
+
+
+ Initializes a new instance of the class.
+
+ The address.
+ The port.
+
+
+
+ Initializes a new instance of the class.
+
+ The address.
+ The port.
+ The HTTP factory.
+
+
+
+ Creates a new instance with default factories.
+
+ Address that the listener should accept connections on.
+ Port that listener should accept connections on.
+ Created HTTP listener.
+
+
+
+ Creates a new instance with default factories.
+
+ Address that the listener should accept connections on.
+ Port that listener should accept connections on.
+ Factory used to create different types in the framework.
+ Created HTTP listener.
+
+
+
+ Creates a new instance with default factories.
+
+ Address that the listener should accept connections on.
+ Port that listener should accept connections on.
+ Certificate to use
+ Created HTTP listener.
+
+
+
+ Create a new context
+
+ Accepted socket
+ A new context.
+
+
+ Throwing exception if in debug mode and not exception handler have been specified.
+
+
+
+ Start listener.
+
+ Number of pending accepts.
+
+ Make sure that you are subscribing on first.
+
+ Listener have already been started.
+ Failed to start socket.
+ Invalid port number.
+
+
+
+ Stop listener.
+
+
+
+
+ Gets HTTP factory used to create types used by this HTTP library.
+
+
+
+
+ Gets or sets the maximum number of bytes that the request body can contain.
+
+ The content length limit.
+
+
+ Used when responding to 100-continue.
+
+
+ 0 = turned off.
+
+
+
+
+
+ Gets listener address.
+
+
+
+
+ Gets if listener is secure.
+
+
+
+
+ Gets if listener have been started.
+
+
+
+
+ Gets or sets logger.
+
+
+
+
+ Gets listening port.
+
+
+
+
+ A new request have been received.
+
+
+
+
+ Can be used to reject certain clients.
+
+
+
+
+ A HTTP exception have been thrown.
+
+
+ Fill the body with a user friendly error page, or redirect to somewhere else.
+
+
+
+
+ Client asks if he may continue.
+
+
+ If the body is too large or anything like that you should respond .
+
+
+
+
+ Initializes a new instance of the class.
+
+ Address to accept new connections on.
+ Port to accept connections on.
+ Certificate securing the connection.
+
+
+
+ Create a new context
+
+ Accepted socket
+ A new context.
+
+ Factory is assigned by the on each incoming request.
+
+
+
+
+ Gets if listener is secure.
+
+
+
+
+
+ Gets or sets SSL protocol.
+
+
+
+
+ Gets or sets if client certificate should be used.
+
+
+
+
+ A response have been received.
+
+
+
+
+ Initializes a new instance of the class.
+
+ The response.
+
+
+
+ Gets or sets response.
+
+
+
+
+ Implements HTTP Digest authentication. It's more secure than Basic auth since password is
+ encrypted with a "key" from the server.
+
+
+ Keep in mind that the password is encrypted with MD5. Use a combination of SSL and digest auth to be secure.
+
+
+
+
+ Authenticates requests
+
+
+
+
+ Authenticate request
+
+ Authorization header send by web client
+ Realm to authenticate in, typically a domain name.
+ HTTP Verb used in the request.
+ User if authentication was successful; otherwise null.
+
+
+
+ Create a authentication challenge.
+
+ Realm that the user should authenticate in
+ A WWW-Authenticate header.
+ If realm is empty or null.
+
+
+
+ Gets authenticator scheme
+
+
+ digest
+
+
+
+
+ Initializes a new instance of the class.
+
+ Supplies users during authentication process.
+
+
+
+ Used by test classes to be able to use hardcoded values
+
+
+
+
+ An authentication response have been received from the web browser.
+ Check if it's correct
+
+ Contents from the Authorization header
+ Realm that should be authenticated
+ GET/POST/PUT/DELETE etc.
+
+ Authentication object that is stored for the request. A user class or something like that.
+
+ if authenticationHeader is invalid
+ If any of the parameters is empty or null.
+
+
+
+ Encrypts parameters into a Digest string
+
+ Realm that the user want to log into.
+ User logging in
+ Users password.
+ HTTP method.
+ Uri/domain that generated the login prompt.
+ Quality of Protection.
+ "Number used ONCE"
+ Hexadecimal request counter.
+ "Client Number used ONCE"
+ Digest encrypted string
+
+
+
+
+
+ Md5 hex encoded "userName:realm:password", without the quotes.
+ Md5 hex encoded "method:uri", without the quotes
+ Quality of Protection
+ "Number used ONCE"
+ Hexadecimal request counter.
+ Client number used once
+
+
+
+
+ Create a authentication challenge.
+
+ Realm that the user should authenticate in
+ A correct auth request.
+ If realm is empty or null.
+
+
+
+ Gets the current nonce.
+
+
+
+
+
+ Gets the Md5 hash bin hex2.
+
+ To be hashed.
+
+
+
+
+ determines if the nonce is valid or has expired.
+
+ nonce value (check wikipedia for info)
+ true if the nonce has not expired.
+
+
+
+ Gets authentication scheme name
+
+
+
+
+ Gets authenticator scheme
+
+
+
+ digest
+
+
+
+
+ Session in the system
+
+
+
+
+ Gets or sets session id.
+
+
+
+
+ Factory creating null logger.
+
+
+
+
+ Initializes a new instance of the class.
+
+
+
+
+ Create a new logger.
+
+ Type that requested a logger.
+ Logger for the specified type;
+
+ MUST ALWAYS return a logger. Return if no logging
+ should be used.
+
+
+
+
+ Logger instance.
+
+
+
+
+ HTTP methods.
+
+
+
+
+ Unknown method
+
+
+
+
+ Posting data
+
+
+
+
+ Get data
+
+
+
+
+ Update data
+
+
+
+
+ Remove data
+
+
+
+
+ Get only HTTP headers.
+
+
+
+
+ Options HTTP 1.1 header.
+
+
+
+
+ Parses .
+
+
+
+
+ Parse a header
+
+ Name of header.
+ Reader containing value.
+ HTTP Header
+ Header value is not of the expected format.
+
+
+
+ Request couldn't be parsed successfully.
+
+
+
+
+ Initializes a new instance of the class.
+
+ Exception description.
+
+
+
+ Initializes a new instance of the class.
+
+ Exception description.
+ Exception description.
+
+
+
+ Arguments for .
+
+
+
+
+ Initializes a new instance of the class.
+
+ The context.
+
+
+
+ Gets or sets thrown exception
+
+
+
+
+ Gets or sets if error page was provided.
+
+
+
+
+ Gets requested resource.
+
+
+
+
+ Gets response to send
+
+
+
+
+ Convention over configuration server.
+
+
+ Used to make it easy to create and use a web server.
+
+ All resources must exist in the "YourProject.Content" namespace (or a subdirectory called "Content" relative to yourapp.exe).
+
+
+
+
+
+ Http server.
+
+
+
+
+ Initializes a new instance of the class.
+
+ Factory used to create objects used in this library.
+
+
+
+ Initializes a new instance of the class.
+
+
+
+
+ Add a decoder.
+
+ decoder to add
+
+ Adding zero decoders will make the server add the
+ default ones which is and .
+
+
+
+
+ Add a new router.
+
+ Router to add
+ Server have been started.
+
+
+
+ Add a file module
+
+ Module to add
+ module is null.
+ Cannot add modules when server have been started.
+
+
+
+ Add a HTTP listener.
+
+
+ Listener have been started.
+
+
+
+ An error have occurred and we need to send a result pack to the client
+
+ The context.
+ The exception.
+
+ Invoke base class () to send the contents
+ of .
+
+
+
+
+ Called before anything else.
+
+ The context.
+
+ Looks after a in the request and will
+ use the if found.
+
+
+
+
+ All server modules are about to be invoked.
+
+ The context.
+
+ Called when routers have been invoked but no modules yet.
+
+
+
+
+ A request have arrived but not yet been processed yet.
+
+ The context.
+
+ Default implementation adds a Date header and Server header.
+
+
+
+
+ Go through all modules and check if any of them can handle the current request.
+
+
+
+
+
+
+ Process result (check if it should be sent back or not)
+
+
+
+ true if request was processed properly.; otherwise false.
+
+
+
+ Processes all routers.
+
+ Request context.
+ Processing result.
+
+
+
+ Requests authentication from the user.
+
+ Host/domain name that the server hosts.
+
+ Used when calculating hashes in Digest authentication.
+
+
+
+
+
+
+ Send a response.
+
+
+
+
+
+
+
+ Start http server.
+
+ Number of pending connections.
+
+
+
+ Stops the server
+
+ true if all modules should be removed.
+
+
+
+ Gets the authentication provider.
+
+
+ A authentication provider is used to keep track of all authentication types
+ that can be used.
+
+
+
+
+ Gets or sets number of bytes that a body can be.
+
+
+
+ Used to determine the answer to a 100-continue request.
+
+
+ 0 = turned off.
+
+
+
+
+
+ Gets current server.
+
+
+ Only valid when a request have been received and is being processed.
+
+
+
+
+ Gets or sets the maximum size of request body (in bytes)
+
+
+
+
+ Gets or sets server name.
+
+
+ Used in the "Server" header when serving requests.
+
+
+
+
+ Invoked just before a response is sent back to the client.
+
+
+
+
+ Invoked *after* the web server has tried to handled the request.
+
+
+ The event can be used to handle the request after all routes and modules
+ have tried to process the request.
+
+
+
+
+ Invoked *before* the web server has tried to handled the request.
+
+
+ Event can be used to load a session from a cookie or to force
+ authentication or anything other you might need t do before a request
+ is handled.
+
+
+
+
+ An error page have been requested.
+
+
+
+
+ Initializes a new instance of the class.
+
+
+
+
+ Class to make dynamic binding of redirects. Instead of having to specify a number of similar redirect rules
+ a regular expression can be used to identify redirect URLs and their targets.
+
+
+ [a-z0-9]+)", "/users/${target}/?find=true", RegexOptions.IgnoreCase)
+ ]]>
+
+
+
+
+ Initializes a new instance of the class.
+
+ Expression to match URL
+ Expression to generate URL
+
+ [a-zA-Z0-9]+)", "/user/${first}"));
+ Result of ie. /employee1 will then be /user/employee1
+ ]]>
+
+
+
+
+ Initializes a new instance of the class.
+
+ Expression to match URL
+ Expression to generate URL
+ Regular expression options to use, can be null
+
+ [a-zA-Z0-9]+)", "/user/{first}", RegexOptions.IgnoreCase));
+ Result of ie. /employee1 will then be /user/employee1
+ ]]>
+
+
+
+
+ Initializes a new instance of the class.
+
+ Expression to match URL
+ Expression to generate URL
+ Regular expression options to apply
+ true if request should be redirected, false if the request URI should be replaced.
+
+ [a-zA-Z0-9]+)", "/user/${first}", RegexOptions.None));
+ Result of ie. /employee1 will then be /user/employee1
+ ]]>
+
+ Argument is null.
+
+
+
+
+ Process the incoming request.
+
+ Request context.
+ Processing result.
+ If any parameter is null.
+
+
+
+ Load resources from disk.
+
+
+
+
+ Default forbidden characters.
+
+
+
+
+ relative to absolute path mappings.
+
+
+
+
+ Initializes a new instance of the class.
+
+
+
+
+ Initializes a new instance of the class.
+
+ Request URI path
+ Disk path
+
+ File names should not be included in URI or path.
+
+
+
+ new FileResources("/files/user/", "C:\\intetpub\\files\users\\");
+
+
+
+
+
+ Add a new resource mapping.
+
+ Request URI path
+ Disk path
+
+ File names should not be included in URI or path.
+
+
+
+ resources.Add("/files/", "C:\\intetpub\\files\\");
+
+
+ absolutePath is not found.
+
+
+
+ check if source contains any of the chars.
+
+ string to check
+ Characters to fined
+
+
+
+
+ Go through all mappings and find requested Uri.
+
+ Uri to get local path for.
+ Path if found; otherwise null.
+
+
+
+ Checks if a resource exists in the specified directory
+
+ Uri path to resource
+ true if resource was found; otherwise false.
+
+
+ if (resources.Exists("/files/user/user.png"))
+ Debug.WriteLine("Resource exists.");
+
+
+
+
+
+ Gets a resource.
+
+ Uri path to resource.
+ Resource
+ Uri contains forbidden characters.
+
+
+ Resource resource = resources.Get("/files/user/user.png");
+
+
+
+
+
+ Find all views in a folder/path.
+
+ Absolute Uri path to files that should be found, can end with wild card.
+ Collection to add all view names to.
+ Uri contains forbidden characters.
+
+ Find("
+
+
+
+
+ Gets or sets forbidden characters.
+
+
+ Used to revoke access to any system files.
+
+
+
+
+ Gets or sets absolute path on disk, including file name.
+
+
+
+
+ Gets or sets relative file path.
+
+
+
+
+ Gets or sets Uri path, excluding file name
+
+
+
+
+ Used to send a response back to the client.
+
+
+
+ Writes a object into a stream.
+
+
+ Important! ResponseWriter do not throw any exceptions. Instead it just logs them and
+ let them die peacefully. This is since the response writer is used from
+ catch blocks here and there.
+
+
+
+
+
+ Sends response using the specified context.
+
+ The context.
+ The response.
+
+
+
+ Converts and sends a string.
+
+
+
+ Encoding used to transfer string
+
+
+
+ Send a body to the client
+
+ Context containing the stream to use.
+ Body to send
+
+
+
+ Send all headers to the client
+
+ Response containing call headers.
+ Content used to send headers.
+
+
+
+ Parses .
+
+
+
+
+ Parse a header
+
+ Name of header.
+ Reader containing value.
+ HTTP Header
+ Header value is not of the expected format.
+
+
+
+ Collection of headers.
+
+
+
+
+ Initializes a new instance of the class.
+
+ Factory used to created headers.
+
+
+
+ Adds a header
+
+
+ Will replace any existing header with the same name.
+
+ header to add
+ header is null.
+ Header name cannot be null.
+
+
+
+ Add a header.
+
+ Header name
+ Header value
+
+ Will try to parse the header and create a object.
+
+ Header value is not correctly formatted.
+ name or value is null.
+
+
+
+ Add a header.
+
+ Header name
+ Header value
+
+ Will try to parse the header and create a object.
+
+ name or value is null.
+
+
+
+ Get a header
+
+ Type that it should be cast to
+ Name of header
+ Header if found and casted properly; otherwise null.
+
+
+
+ Returns an enumerator that iterates through the collection.
+
+
+ A that can be used to iterate through the collection.
+
+ 1
+
+
+
+ Returns an enumerator that iterates through a collection.
+
+
+ An object that can be used to iterate through the collection.
+
+ 2
+
+
+
+ Gets a header
+
+ header name.
+ header if found; otherwise null.
+
+
+
+ Used to authenticate users
+
+
+ Authentication is requested by throwing
+
+
+
+
+ Implements basic authentication scheme.
+
+
+
+
+ Create a response that can be sent in the WWW-Authenticate header.
+
+ Realm that the user should authenticate in
+ Not used by basic authentication
+ A WWW-Authenticate header.
+ Argument is null.
+
+
+
+ An authentication response have been received from the web browser.
+ Check if it's correct
+
+ Authorization header
+ Realm that should be authenticated
+ GET/POST/PUT/DELETE etc.
+ Authentication object that is stored for the request. A user class or something like that.
+ if authenticationHeader is invalid
+ If any of the paramters is empty or null.
+
+
+
+ Gets authenticator scheme
+
+
+
+ digest
+
+
+
+
+ Request implementation.
+
+
+
+
+ Initializes a new instance of the class.
+
+ The method.
+ The path.
+ The version.
+
+
+
+ Get a header
+
+ Type that it should be cast to
+ Name of header
+ Header if found and casted properly; otherwise null.
+
+
+
+ Add a new header.
+
+
+
+
+
+
+ Add a new header.
+
+ Header to add.
+
+
+
+ Returns an enumerator that iterates through the collection.
+
+
+ A that can be used to iterate through the collection.
+
+ 1
+
+
+
+ Returns an enumerator that iterates through a collection.
+
+
+ An object that can be used to iterate through the collection.
+
+ 2
+
+
+
+ Gets a header.
+
+
+
+
+
+
+ Gets request URI.
+
+
+
+
+ Gets cookies.
+
+
+
+
+ Gets all uploaded files.
+
+
+
+
+ Gets query string and form parameters
+
+
+
+
+ Gets form parameters.
+
+
+
+
+ Gets query string.
+
+
+
+
+ Gets if request is an Ajax request.
+
+
+
+
+ Gets or sets connection header.
+
+
+
+
+ Gets or sets HTTP version.
+
+
+
+
+ Gets or sets HTTP method.
+
+
+
+
+ Gets requested URI.
+
+
+
+
+ Kind of content in the body
+
+ Default is text/html
+
+
+
+ Gets or sets encoding
+
+
+
+
+ Gets headers.
+
+
+
+
+ Gets body stream.
+
+
+
+
+ Size of the body. MUST be specified before sending the header,
+ unless property Chunked is set to true.
+
+
+ Any specifically assigned value or Body stream length.
+
+
+
+
+ Initializes a new instance of the class.
+
+ SSL protocol to use.
+ The socket.
+ The context.
+ Server certificate to use.
+
+
+
+ Create stream used to send and receive bytes from the socket.
+
+ Socket to wrap
+ Stream
+ Stream could not be created.
+
+
+
+ Gets or sets client certificate.
+
+
+
+
+ Gets used protocol.
+
+
+
+
+ Gets or sets if client certificate should be used instead of server certificate.
+
+
+
+
+ A list of request cookies.
+
+
+
+
+ Let's copy all the cookies.
+
+ value from cookie header.
+
+
+
+ Initializes a new instance of the class.
+
+
+
+
+ Adds a cookie in the collection.
+
+ cookie to add
+ cookie is null
+ Name must be specified.
+
+
+
+ Remove all cookies.
+
+
+
+
+ Remove a cookie from the collection.
+
+ Name of cookie.
+
+
+
+ Gets a collection enumerator on the cookie list.
+
+ collection enumerator
+
+
+
+ Returns an enumerator that iterates through the collection.
+
+
+
+ A that can be used to iterate through the collection.
+
+ 1
+
+
+
+ Gets the count of cookies in the collection.
+
+
+
+
+ Gets the cookie of a given identifier (null if not existing).
+
+
+
+
+ Parses query string
+
+
+
+
+ Parse a query string
+
+ string to parse
+ A collection
+ reader is null.
+
+
+
+ Parse a query string
+
+ string to parse
+ A collection
+ queryString is null.
+
+
+
+ Stores sessions in files.
+
+
+ All session parameters must be serializable.
+
+
+
+
+ Stores sessions in your favorite store
+
+
+
+
+
+
+
+ Saves the specified session.
+
+ The session.
+
+
+
+ Touches the specified session
+
+ Session id.
+
+ Used to prevent sessions from expiring.
+
+
+
+
+ Loads a session
+
+ Session id.
+ Session if found; otherwise null.
+
+
+
+ Delete a session
+
+ Id of session
+
+
+
+ Saves the specified session.
+
+ The session.
+
+
+
+ Touches the specified session
+
+ Session id.
+
+ Used to prevent sessions from expiring.
+
+
+
+
+ Loads a session
+
+ Session id.
+ Session if found; otherwise null.
+
+
+
+ Create a HTTP response object.
+
+
+
+
+ Initializes a new instance of the class.
+
+ HTTP Version.
+ HTTP status code.
+ Why the status code was selected.
+ Version must start with 'HTTP/'
+
+
+
+ Initializes a new instance of the class.
+
+ Context that the response will be sent through.
+ Request that the response is for.
+ Version must start with 'HTTP/'
+
+
+
+ Redirect user.
+
+ Where to redirect to.
+
+ Any modifications after a redirect will be ignored.
+
+
+
+
+ Add a new header.
+
+
+
+
+
+
+ Add a new header.
+
+ Header to add.
+
+
+
+ Returns an enumerator that iterates through the collection.
+
+
+ A that can be used to iterate through the collection.
+
+ 1
+
+
+
+ Returns an enumerator that iterates through a collection.
+
+
+ An object that can be used to iterate through the collection.
+
+ 2
+
+
+
+ Gets a header.
+
+
+
+
+
+
+ Gets connection type.
+
+
+
+
+ Status code that is sent to the client.
+
+ Default is
+
+
+
+ Gets HTTP version.
+
+
+ Default is HTTP/1.1
+
+
+
+
+ Information about why a specific status code was used.
+
+
+
+
+ Size of the body. MUST be specified before sending the header,
+ unless property Chunked is set to true.
+
+
+ Any specifically assigned value or Body stream length.
+
+
+
+
+ Kind of content in the body
+
+ Default is text/html
+
+
+
+ Gets or sets encoding
+
+
+
+
+ Gets cookies.
+
+
+
+
+ Gets body stream.
+
+
+
+
+ Gets headers.
+
+
+
+
+ Loads resources that are embedded in assemblies.
+
+
+ No locks used internally since all mappings are loaded during start up.
+
+
+
+
+ Initializes a new instance of the class.
+
+
+
+
+ Initializes a new instance of the class.
+
+ Path (Uri) requested by clients
+ Assembly that the resources exist in
+ Name space that the resources exist in
+
+
+
+ Add a specific resource.
+
+ Path (Uri) requested by clients
+ Assembly that the resources exist in
+ Name space to root folder under (all name spaces below the specified one are considered as folders)
+ Name space and name of resource.
+
+
+ Add("/", Assembly.GetExecutingAssembly(), "MyApplication.Files", "Myapplication.Files.Images.MyImage.png");
+
+
+
+
+
+ Add resources.
+
+ Path (Uri) requested by clients
+ Assembly that the resources exist in
+ Name of resource, including name space.
+ true if file was found (and has not previously been added); otherwise false.
+
+
+
+
+
+ Add resources in a specific path (will not work with sub folders)
+
+ Path (Uri) requested by clients
+ Assembly that the resources exist in
+ Name space to root folder under which all name spaces exists in,
+ true if any files was found; otherwise false.
+
+
+ Adds all views in the specified folder. Sub folders are not supported since it's hard to determine
+ with parts are the path and witch parts are the filename. Use to get support
+ for sub folders.
+
+
+
+
+ Add("/user/", typeof(MyController).Assembly, "YourProject.Users.Views");
+
+
+
+
+
+ Add resources in a folder and it's sub folder
+
+
+
+
+
+ This method is not going to map files but keep the mapping and
+ try to look up views every time they are requested. This is the method
+ to use to add a resource folder that has sub folders.
+
+
+
+
+
+ Tries to load file by using previously added paths.
+
+ Uri path including file name
+
+
+
+
+ Checks if a resource exists in the specified directory
+
+ Uri path to resource
+ true if resource was found; otherwise false.
+
+
+ if (resources.Exists("/files/user/user.png"))
+ Debug.WriteLine("Resource exists.");
+
+
+
+
+
+ Load a resource.
+
+ Uri of resource.
+ Resource if found and loaded; otherwise null.
+
+
+
+ Find all views in a folder/path.
+
+ Uri path
+ Collection to add all view names to.
+
+
+
+ Loads all files in a resource directory
+
+
+
+
+
+ Gets or sets assembly that the resource exists in.
+
+
+
+
+ Gets or sets resource name.
+
+
+
+
+ Gets or sets full name space path to resource.
+
+
+
+
+ Gets or sets if this file is for a certain content type.
+
+
+
+
+ Gets or sets full "virtual" Uri path, excluding file name.
+
+
+
+
+ Gets or sets assembly
+
+
+
+
+ Gets or sets name space root.
+
+
+
+
+ Gets or sets uri path.
+
+
+
+
+ Something unexpected went wrong.
+
+
+
+
+ Initializes a new instance of the class.
+
+ Exception description.
+
+
+
+ Initializes a new instance of the class.
+
+ Exception description.
+ Inner exception.
+
+
+
+ Decodes URL encoded values.
+
+
+
+
+
+
+ Stream containing the content
+ Content type header
+ Stream encoding
+ Collection with all parameters.
+ Body format is invalid for the specified content type.
+ Failed to read all bytes from body stream.
+
+
+
+ All content types that the decoder can parse.
+
+ A collection of all content types that the decoder can handle.
+
+
+
+ Parses and builds messages
+
+
+ The message factory takes care of building messages
+ from all end points.
+
+ Since both message and packet protocols are used, the factory
+ hands out contexts to all end points. The context keeps a state
+ to be able to parse partial messages properly.
+
+
+ Each end point need to hand the context back to the message factory
+ when the client disconnects (or a message have been parsed).
+
+
+
+
+
+ Initializes a new instance of the class.
+
+ Factory used to create headers.
+
+
+
+ Create a new message factory context.
+
+ A new context.
+
+ A context is used to parse messages from a specific endpoint.
+
+
+
+
+ Release a used factory context.
+
+
+
+
+
+ A request have been received from one of the end points.
+
+
+
+
+ A response have been received from one of the end points.
+
+
+
+
+ Priority for log entries
+
+
+
+
+
+ Very detailed logs to be able to follow the flow of the program.
+
+
+
+
+ Logs to help debug errors in the application
+
+
+
+
+ Information to be able to keep track of state changes etc.
+
+
+
+
+ Something did not go as we expected, but it's no problem.
+
+
+
+
+ Something that should not fail failed, but we can still keep
+ on going.
+
+
+
+
+ Something failed, and we cannot handle it properly.
+
+
+
+
+ Parses .
+
+
+
+
+ Parse a header
+
+ Name of header.
+ Reader containing value.
+ HTTP Header
+ Header value is not of the expected format.
+
+
+
+ Form parameters where form string arrays have been converted to real arrays.
+
+
+
+
+ Initializes a new instance of the class.
+
+
+
+
+ Initializes a new instance of the class.
+
+ The name.
+ The value.
+
+
+
+ Initializes a new instance of the class.
+
+ Parse parameters from the this collection.
+
+
+
+ Get a parameter.
+
+
+
+
+
+
+ Add a parameter
+
+ Name of parameter, can contain a string array.
+ Value
+
+
+ ArrayParameterCollection array = new ArrayParameterCollection();
+ array.Add("user[FirstName]", "Jonas");
+ array.Add("user[FirstName]", "Arne");
+ string firstName = array["user"]["FirstName"].Value; // "Arne" is returned
+ foreach (string value in array["user"]["FirstName"])
+ Console.WriteLine(value); // each name is displayed.
+
+
+
+
+
+ Checks if the specified parameter exists
+
+ Parameter name.
+ true if found; otherwise false;
+
+
+
+ Returns an enumerator that iterates through the collection.
+
+
+ A that can be used to iterate through the collection.
+
+ 1
+
+
+
+ Gets first value of an item.
+
+
+ String if found; otherwise null.
+
+
+
+ Gets number of parameters.
+
+
+
+
+ Gets last value of an parameter.
+
+ Parameter name
+ String if found; otherwise null.
+
+
+
+ Assign properties from HTTP parameters.
+
+
+
+
+ Used to filter out properties.
+
+ Filter handler.
+ Handler have already been set.
+
+
+
+ Assign properties in the specified object.
+
+ Object to fill.
+ Contains all parameters that should be assigned to the properties.
+ Properties was not found or value could not be converted.
+ Any parameter is null.
+
+
+
+ Used to be able to filter properties
+
+ Model having it's properties assigned
+ Property about to be assigned
+ Value to assign
+ true if value can be set; otherwise false.
+
+
+
+ Failed to assign properties.
+
+
+
+
+ Initializes a new instance of the class.
+
+ The property errors.
+
+
+
+ Gets all errors during assignment.
+
+
+ Dictionary key is property name.
+
+
+
+
+ Requested resource may not be accessed.
+
+
+ Normally thrown after an authentication attempt have failed too many times.
+
+
+
+
+
+ Initializes a new instance of the class.
+
+ Exception description.
+
+
+
+ Initializes a new instance of the class.
+
+ Exception description.
+ Inner exception.
+
+
+
+ User needs to authenticate.
+
+
+
+
+
+
+ Initializes a new instance of the class.
+
+ Exception description.
+
+
+
+ Initializes a new instance of the class.
+
+ Exception description.
+ Inner exception.
+
+
+
+ First line in a response have been received
+
+
+
+
+ Gets or sets motivation to why the status code was used.
+
+
+
+
+ Gets or sets message status code
+
+
+
+
+ Gets or sets sip protocol version used.
+
+
+
+
+ Request context
+
+
+ Contains information about a HTTP request and where it came from.
+
+
+
+
+ Gets or sets http context.
+
+
+
+
+ Gets or sets http request.
+
+
+
+
+ Gets or sets http response.
+
+
+
+
+ Header for "Date" and "If-Modified-Since"
+
+
+
+ The field value is an HTTP-date, as described in section 3.3.1 in RFC2616;
+ it MUST be sent in RFC 1123 [8]-date format. An example is
+
+ Date: Tue, 15 Nov 1994 08:12:31 GMT
+
+ Origin servers MUST include a Date header field in all
+ responses, except in these cases:
+
+ - If the response status code is 100 (Continue) or 101 (Switching
+ Protocols), the response MAY include a Date header field, at the server's
+ option.
+
- If the response status code conveys a server error, e.g. 500
+ (Internal Server Error) or 503 (Service Unavailable), and it is inconvenient
+ or impossible to generate a valid Date.
+
- If the server does not have a clock that can provide a
+ reasonable approximation of the current time, its responses MUST NOT include
+ a Date header field. In this case, the rules in section 14.18.1 in RFC2616
+ MUST be followed.
+
+
+ A received message that does not have a Date header field MUST
+ be assigned one by the recipient if the message will be cached by that
+ recipient or gatewayed via a protocol which requires a Date. An HTTP
+ implementation without a clock MUST NOT cache responses without revalidating
+ them on every use. An HTTP cache, especially a shared cache, SHOULD use a
+ mechanism, such as NTP [28], to synchronize its clock with a reliable
+ external standard.
+ Clients SHOULD only send a Date header field in messages that
+ include an entity-body, as in the case of the PUT and POST requests, and
+ even then it is optional. A client without a clock MUST NOT send a Date
+ header field in a request.
+ The HTTP-date sent in a Date header SHOULD NOT represent a date
+ and time subsequent to the generation of the message. It SHOULD represent
+ the best available approximation of the date and time of message generation,
+ unless the implementation has no means of generating a reasonably accurate
+ date and time. In theory, the date ought to represent the moment just before
+ the entity is generated. In practice, the date can be generated at any time
+ during the message origination without affecting its semantic value.
+
+
+
+
+
+ Header name
+
+
+
+
+ Initializes a new instance of the class.
+
+ Header name.
+ Name must not be empty.
+
+
+
+ Initializes a new instance of the class.
+
+ Header name.
+ Universal time.
+
+
+
+ Returns data formatted as a HTTP header value.
+
+
+ A that represents the current .
+
+
+
+
+ Gets or sets date time.
+
+ Should be in UTC.
+
+
+
+ Gets header name
+
+
+
+
+ The Cache-Control general-header field is used to specify directives that
+ MUST be obeyed by all caching mechanisms along the request/response
+ chain. .
+
+
+
+ The directives specify behavior intended to prevent caches from adversely
+ interfering with the request or response. These directives typically
+ override the default caching algorithms. Cache directives are
+ unidirectional in that the presence of a directive in a request does not
+ imply that the same directive is to be given in the response.
+ Note that HTTP/1.0 caches might not implement Cache-Control and
+ might only implement Pragma: no-cache (see section 14.32 in RFC2616).
+ Cache directives MUST be passed through by a proxy or gateway
+ application, regardless of their significance to that application, since the
+ directives might be applicable to all recipients along the request/response
+ chain. It is not possible to specify a cache- directive for a specific cache
+
+
+ When a directive appears without any 1#field-name parameter, the
+ directive applies to the entire request or response. When such a
+ directive appears with a 1#field-name parameter, it applies only to
+ the named field or fields, and not to the rest of the request or
+ response. This mechanism supports extensibility; implementations of
+ future versions of the HTTP protocol might apply these directives to
+ header fields not defined in HTTP/1.1.
+
+
+ The cache-control directives can be broken down into these general
+ categories:
+
+ -
+ Restrictions on what are cacheable; these may only be imposed by
+ the origin server.
+
-
+ Restrictions on what may be stored by a cache; these may be
+ imposed by either the origin server or the user agent.
+
-
+ Modifications of the basic expiration mechanism; these may be
+ imposed by either the origin server or the user agent.
+
-
+ Controls over cache revalidation and reload; these may only be
+ imposed by a user agent.
+
-
+ Control over transformation of entities.
+
-
+ Extensions to the caching system.
+
+
+
+
+
+
+
+ Header name
+
+
+
+
+ Gets header name
+
+
+
+
+ Authorization response
+
+
+
+ A user agent that wishes to authenticate itself with a server--
+ usually, but not necessarily, after receiving a 401 response--does
+ so by including an Authorization request-header field with the
+ request. The Authorization field value consists of credentials
+ containing the authentication information of the user agent for
+ the realm of the resource being requested.
+
+
+ Authorization = "Authorization" ":" credentials
+
+
+ HTTP access authentication is described in "HTTP Authentication:
+ Basic and Digest Access Authentication" [43]. If a request is
+ authenticated and a realm specified, the same credentials SHOULD
+ be valid for all other requests within this realm (assuming that
+ the authentication scheme itself does not require otherwise, such
+ as credentials that vary according to a challenge value or using
+ synchronized clocks).
+ When a shared cache (see section 13.7) receives a request
+ containing an Authorization field, it MUST NOT return the
+ corresponding response as a reply to any other request, unless one
+ of the following specific exceptions holds:
+
+
+ -
+ If the response includes the "s-maxage" cache-control
+ directive, the cache MAY use that response in replying to a
+ subsequent request. But (if the specified maximum age has
+ passed) a proxy cache MUST first revalidate it with the origin
+ server, using the request-headers from the new request to allow
+ the origin server to authenticate the new request. (This is the
+ defined behavior for s-maxage.) If the response includes "s-
+ maxage=0", the proxy MUST always revalidate it before re-using
+ it.
+
-
+ If the response includes the "must-revalidate" cache-control
+ directive, the cache MAY use that response in replying to a
+ subsequent request. But if the response is stale, all caches
+ MUST first revalidate it with the origin server, using the
+ request-headers from the new request to allow the origin server
+ to authenticate the new request.
+
-
+ If the response includes the "public" cache-control directive,
+ it MAY be returned in reply to any subsequent request.
+
+
+
+
+
+
+ Name constant
+
+
+
+
+ Gets or sets authentication data.
+
+
+
+
+ Gets or sets authentication protocol.
+
+
+
+
+ Gets name of header.
+
+
+
+
+ Factory is used to create new logs in the system.
+
+
+
+
+ Assigns log factory being used.
+
+ The log factory.
+ A factory have already been assigned.
+
+
+
+ Create a new logger.
+
+ Type that requested a logger.
+ Logger for the specified type;
+
+
+
+ A request have been received.
+
+
+
+
+
+
+ Initializes a new instance of the class.
+
+ context that received the request.
+ Received request.
+ Response to send.
+
+
+
+ Gets context that received the request.
+
+
+ Do not forget to set to true if you are sending
+ back a response manually through .
+
+
+
+
+ Gets or sets if the request have been handled.
+
+
+ The library will not attempt to send the response object
+ back to the client if this property is set to true.
+
+
+
+
+ Gets request object.
+
+
+
+
+ Gets response object.
+
+
+
+
+ Get or create components used in the web server framework
+
+
+
+
+
+
+
+ Get or create a type.
+
+ Type to create
+ Created type.
+
+ Gets or creates types in the framework.
+ Check for more information on which
+ types the factory should contain.
+
+
+
+
+ Parses numerical values
+
+
+
+
+ Parse a header
+
+ Name of header.
+ Reader containing value.
+ HTTP Header
+ Header value is not of the expected format.
+
+
+
+ Contains parameters for HTTP headers.
+
+
+
+
+ Add a parameter
+
+ name
+ value
+
+ Existing parameter with the same name will be replaced.
+
+
+
+
+ Parse parameters.
+
+ Parser containing buffer to parse.
+ A collection with all parameters (or just a empty collection).
+ Expected a value after equal sign.
+
+
+
+ Parse parameters.
+
+ Parser containing buffer to parse.
+ Parameter delimiter
+ A collection with all parameters (or just a empty collection).
+ Expected a value after equal sign.
+
+
+
+ Returns a that represents the current .
+
+
+ A that represents the current .
+
+
+
+
+ Gets or sets a value
+
+ parameter name
+ value if found; otherwise null.
+
+
+
+ Component that should be registered in the container.
+
+
+ Register using all interfaces that is specified in this assembly.
+
+
+
+
+ Stream-based multipart handling.
+
+ In this incarnation deals with an HttpInputStream as we are now using
+ IntPtr-based streams instead of byte []. In the future, we will also
+ send uploads above a certain threshold into the disk (to implement
+ limit-less HttpInputFiles).
+
+
+ Taken from HttpRequest in mono (http://www.mono-project.com)
+
+
+
+
+ Interface used to write to log files.
+
+
+ If you want to use the built in filtering mechanism, create a constructor
+ which takes one parameter, a .
+
+
+
+
+ Write an entry that helps when debugging code.
+
+ Log message
+
+
+
+ Write an entry that helps when debugging code.
+
+ Log message
+ Thrown exception to log.
+
+
+
+ Something went wrong, but the application do not need to die. The current thread/request
+ cannot continue as expected.
+
+ Log message
+
+
+
+ Something went wrong, but the application do not need to die. The current thread/request
+ cannot continue as expected.
+
+ Log message
+ Thrown exception to log.
+
+
+
+ Something went very wrong, application might not recover.
+
+ Log message
+
+
+
+ Something went very wrong, application might not recover.
+
+ Log message
+ Thrown exception to log.
+
+
+
+ Informational message, needed when helping customer to find a problem.
+
+ Log message
+
+
+
+ Informational message, needed when helping customer to find a problem.
+
+ Log message
+ Thrown exception to log.
+
+
+
+ Write a entry that helps when trying to find hard to find bugs.
+
+ Log message
+
+
+
+ Write a entry that helps when trying to find hard to find bugs.
+
+ Log message
+ Thrown exception to log.
+
+
+
+ Something is not as we expect, but the code can continue to run without any changes.
+
+ Log message
+
+
+
+ Something is not as we expect, but the code can continue to run without any changes.
+
+ Log message
+ Thrown exception to log.
+
+
+
+ Used to create all key types in the HTTP server.
+
+
+ Should have factory methods at least for the following types:
+ , ,
+ , ,
+ , ,
+ , ,
+ .
+
+ Check the default implementations to see which constructor
+ parameters you will get.
+
+
+ HttpFactory.Add(typeof(IRequest), (type, args) => new MyRequest((string)args[0]));
+
+
+
+
+
+ Initializes a new instance of the class.
+
+
+
+
+ Add a factory method for a type.
+
+ Type to create
+ Method creating the type.
+
+
+
+ Used to
+
+
+
+
+
+
+ Setup our singleton.
+
+
+
+
+
+ We want to use a singleton, but we also want to be able
+ to let the developer to setup his own header factory.
+ Therefore we use this method to create our own factory only if the user
+ have not specified one.
+
+
+
+
+ Small method to create a message factory singleton and replace then default delegate method.
+
+
+
+
+
+
+
+ Create a type.
+
+ Type to create
+ Created type.
+
+
+
+ Gets http factory for the current listener.
+
+
+
+
+ Delegate used to create a certain type
+
+ Created type.
+
+ Method must never fail.
+
+
+
+
+ Contains numerical value.
+
+
+
+
+ Initializes a new instance of the class.
+
+ The name.
+ The value.
+
+
+
+ Returns data formatted as a HTTP header value.
+
+
+ A that represents the current .
+
+
+
+
+ Gets value
+
+
+
+
+ Gets header name
+
+
+
+
+ Contents of a cookie header.
+
+
+
+
+ Initializes a new instance of the class.
+
+ The collection.
+ collection is null.
+
+
+
+ Gets cookie collection
+
+
+
+
+ Gets header name
+
+
+
+
+ Gets value as it would be sent back to client.
+
+
+
+
+
+ Data decoded from a POST body.
+
+
+
+
+ Initializes a new instance of the class.
+
+
+
+
+ Gets or sets decoded files.
+
+
+
+
+ Gets or sets decoded parameters.
+
+
+
+
+ Collection of body decoders.
+
+
+ Body decoders are used to parse request body and convert it
+ into a and a .
+
+
+
+
+ Add another body decoder.
+
+
+
+
+
+ Decode body stream
+
+ Stream containing the content
+ Content type header
+ Stream encoding
+ Decoded data.
+ Body format is invalid for the specified content type.
+ Something unexpected failed.
+
+
+
+ Returns an enumerator that iterates through the collection.
+
+
+ A that can be used to iterate through the collection.
+
+ 1
+
+
+
+ Returns an enumerator that iterates through a collection.
+
+
+ An object that can be used to iterate through the collection.
+
+ 2
+
+
+
+ Gets number of decoders.
+
+
+
+
+ Credits and description: http://theinstructionlimit.com/?p=76
+
+
+ Converted to .Net 2.0
+
+
+
+
+ Type cached for fast property value modifications.
+
+
+
+
+ Get a property value.
+
+ Instance to get value from.
+ Name of property.
+ Property value.
+
+
+
+ Assign a value, try to convert it if it's not the same type as the property type.
+
+ Object containing the property
+ Name of property
+ Value to convert and assign
+ Failed to find property.
+ Could not convert value type to property type.
+
+
+
+ Assign value to a property
+
+ Object containing the property
+ Name of property
+ Value to assign, must be of the same type as the property.
+ Failed to find property.
+
+
+
+ Used to cache property information
+
+
+
+
+ Gets the property.
+
+ The name.
+
+ Failed to find property.
+
+
+ InvalidCastException.
+
+
+
+ Get a property value.
+
+ Instance to get value from.
+ Name of property.
+ Property value.
+
+
+
+ Assign a value, try to convert it if it's not the same type as the property type.
+
+ Object containing the property
+ Name of property
+ Value to convert and assign
+ Failed to find property.
+ Could not convert value type to property type.
+
+
+
+ Assign value to a property
+
+ Object containing the property
+ Name of property
+ Value to assign, must be of the same type as the property.
+ Failed to find property.
+
+
+
+ Gets or sets member info
+
+
+
+
+ Gets or sets member type
+
+
+
+
+ A request have been received.
+
+
+
+
+ Initializes a new instance of the class.
+
+ The request.
+ End point that the request was received from.
+
+
+
+ End point that the message was received from.
+
+
+
+
+ Received request.
+
+
+
+
+ Creates a single message for one of the end points.
+
+
+ The factory is
+
+
+
+
+ Initializes a new instance of the class.
+
+ The MSG factory.
+ The factory.
+ The parser.
+
+
+
+ Performs application-defined tasks associated with freeing, releasing, or resetting unmanaged resources.
+
+ 2
+
+
+
+ Received a header from parser
+
+
+
+
+
+
+ Will continue the parsing until nothing more can be parsed.
+
+ buffer to parse
+ where to start in the buffer
+ number of bytes to process.
+ Position where parser stopped parsing.
+ Parsing failed.
+
+
+
+ Reset parser.
+
+
+ Something failed, reset parser so it can start on a new request.
+
+
+
+
+ A request have been successfully parsed.
+
+
+
+
+ A response have been successfully parsed.
+
+
+
+
+ Client asks if he may continue.
+
+
+ If the body is too large or anything like that you should respond .
+
+
+
+
+ Used to notify about 100-continue header.
+
+
+
+
+ Initializes a new instance of the class.
+
+ request that want to continue.
+
+
+
+ Gets request that want to continue
+
+
+
+
+ Default log writer, writes everything to void (nowhere).
+
+
+
+
+
+ The logging instance.
+
+
+
+
+ Write an entry that helps when debugging code.
+
+ Log message
+
+
+
+ Write an entry that helps when debugging code.
+
+ Log message
+ Thrown exception to log.
+
+
+
+ Write a entry needed when following through code during hard to find bugs.
+
+ Log message
+
+
+
+ Write a entry that helps when trying to find hard to find bugs.
+
+ Log message
+ Thrown exception to log.
+
+
+
+ Informational message, needed when helping customer to find a problem.
+
+ Log message
+
+
+
+ Informational message, needed when helping customer to find a problem.
+
+ Log message
+ Thrown exception to log.
+
+
+
+ Something is not as we expect, but the code can continue to run without any changes.
+
+ Log message
+
+
+
+ Something is not as we expect, but the code can continue to run without any changes.
+
+ Log message
+ Thrown exception to log.
+
+
+
+ Something went wrong, but the application do not need to die. The current thread/request
+ cannot continue as expected.
+
+ Log message
+
+
+
+ Something went wrong, but the application do not need to die. The current thread/request
+ cannot continue as expected.
+
+ Log message
+ Thrown exception to log.
+
+
+
+ Something went very wrong, application might not recover.
+
+ Log message
+
+
+
+ Something went very wrong, application might not recover.
+
+ Log message
+ Thrown exception to log.
+
+
+
+ This class writes to the console.
+
+
+ It colors the output depending on the log level
+ and includes a 3-level stack trace (in debug mode)
+
+
+
+
+
+ Initializes a new instance of the class.
+
+ Type being logged.
+ Log filter.
+
+
+
+ Get color for the specified log level
+
+ Level for the log entry
+ A for the level
+
+
+
+ Write an entry
+
+ Importance of the log message
+ The message.
+
+
+
+ Write an entry that helps when debugging code.
+
+ Log message
+
+
+
+ Write an entry that helps when debugging code.
+
+ Log message
+ Thrown exception to log.
+
+
+
+ Write a entry needed when following through code during hard to find bugs.
+
+ Log message
+
+
+
+ Write a entry that helps when trying to find hard to find bugs.
+
+ Log message
+ Thrown exception to log.
+
+
+
+ Informational message, needed when helping customer to find a problem.
+
+ Log message
+
+
+
+ Informational message, needed when helping customer to find a problem.
+
+ Log message
+ Thrown exception to log.
+
+
+
+ Something is not as we expect, but the code can continue to run without any changes.
+
+ Log message
+
+
+
+ Something is not as we expect, but the code can continue to run without any changes.
+
+ Log message
+ Thrown exception to log.
+
+
+
+ Something went wrong, but the application do not need to die. The current thread/request
+ cannot continue as expected.
+
+ Log message
+
+
+
+ Something went wrong, but the application do not need to die. The current thread/request
+ cannot continue as expected.
+
+ Log message
+ Thrown exception to log.
+
+
+
+ Something went very wrong, application might not recover.
+
+ Log message
+
+
+
+ Something went very wrong, application might not recover.
+
+ Log message
+ Thrown exception to log.
+
+
+
+ Gets or sets type that the logger is for
+
+
+
+
+ Creates a console logger.
+
+
+
+
+ Initializes a new instance of the class.
+
+ The filter.
+
+
+
+ Create a new logger.
+
+ Type that requested a logger.
+ Logger for the specified type;
+
+ MUST ALWAYS return a logger. Return if no logging
+ should be used.
+
+
+
+
+ Cookies that should be set.
+
+
+
+
+ Adds a cookie in the collection.
+
+ cookie to add
+ cookie is null
+ Name and Content must be specified.
+
+
+
+ Copy a request cookie
+
+
+ When the cookie should expire
+
+
+
+ Remove all cookies
+
+
+
+
+ Gets a collection enumerator on the cookie list.
+
+ collection enumerator
+
+
+
+ Returns an enumerator that iterates through the collection.
+
+
+
+ A that can be used to iterate through the collection.
+
+ 1
+
+
+
+ Gets the count of cookies in the collection.
+
+
+
+
+ Gets the cookie of a given identifier.
+
+ Cookie if found; otherwise null.
+
+
+
+ Provider returning user to be authenticated.
+
+
+
+
+ Lookups the specified user
+
+ User name.
+ Typically web server domain name.
+ User if found; otherwise null.
+
+ User name can basically be anything. For instance name entered by user when using
+ basic or digest authentication, or SID when using Windows authentication.
+
+
+
+
+ Gets the principal to use.
+
+ Successfully authenticated user.
+
+
+ Invoked when a user have successfully been authenticated.
+
+
+
+
+
+
+ User information used during authentication process.
+
+
+
+
+ Gets or sets user name used during authentication.
+
+
+
+
+ Gets or sets unencrypted password.
+
+
+ Password as clear text. You could use instead if your passwords
+ are encrypted in the database.
+
+
+
+
+ Gets or sets HA1 hash.
+
+
+
+ Digest authentication requires clear text passwords to work. If you
+ do not have that, you can store a HA1 hash in your database (which is part of
+ the Digest authentication process).
+
+
+ A HA1 hash is simply a Md5 encoded string: "UserName:Realm:Password". The quotes should
+ not be included. Realm is the currently requested Host (as in Request.Headers["host"]).
+
+
+ Leave the string as null if you are not using HA1 hashes.
+
+
+
+
+
+ Provides authentication in the web server.
+
+
+ To initiate authentication you just need to throw a Una
+
+
+
+
+ Add a authenticator.
+
+
+
+
+
+ Authenticate request.
+
+
+
+
+ Requires that a AuthorizationHeader have been sent by the client. If not,
+ request one by sending a WWW-Authentication header (can be generated by the Challenge method).
+
+ Authorization header was not found in the request.
+ Requested authentication scheme is not supported.
+
+
+
+ Create a challenge header (WWW-authenticate)
+
+ Response that the authentication header should be added to
+ Realm that the user should authenticate in
+ WWW-Authenticate header.
+
+
+ Scheme can currently be basic or digest. Basic is not very safe, but easier to use.
+ Digest is quite safe.
+
+
+
+ Requested scheme is not supported.
+
+
+
diff --git a/TShockAPI/ConfigFile.cs b/TShockAPI/ConfigFile.cs
index 3faf935f..7a243147 100644
--- a/TShockAPI/ConfigFile.cs
+++ b/TShockAPI/ConfigFile.cs
@@ -187,6 +187,18 @@ namespace TShockAPI
[Description("This will announce a player's location on join")]
public bool EnableGeoIP = false;
+ [Description("This will turn on a token requirement for the /status API endpoint.")]
+ public bool EnableTokenEndpointAuthentication = false;
+
+ [Description("This is used when the API endpoint /status is queried.")]
+ public string ServerNickname = "TShock Server";
+
+ [Description("Enable/Disable the rest api.")]
+ public bool RestApiEnabled = false;
+
+ [Description("This is the port which the rest api will listen on.")]
+ public int RestApiPort = 7878;
+
public static ConfigFile Read(string path)
{
if (!File.Exists(path))
diff --git a/TShockAPI/Properties/AssemblyInfo.cs b/TShockAPI/Properties/AssemblyInfo.cs
index 13fd0a20..ba4d3fd1 100644
--- a/TShockAPI/Properties/AssemblyInfo.cs
+++ b/TShockAPI/Properties/AssemblyInfo.cs
@@ -36,5 +36,5 @@ using System.Runtime.InteropServices;
// [assembly: AssemblyVersion("1.0.*")]
-[assembly: AssemblyVersion("3.3.0.0904")]
-[assembly: AssemblyFileVersion("3.3.0.0904")]
+[assembly: AssemblyVersion("3.3.2.0905")]
+[assembly: AssemblyFileVersion("3.3.2.0905")]
diff --git a/TShockAPI/Rest/Rest.cs b/TShockAPI/Rest/Rest.cs
new file mode 100644
index 00000000..4c9c9e9f
--- /dev/null
+++ b/TShockAPI/Rest/Rest.cs
@@ -0,0 +1,141 @@
+using System;
+using System.Collections.Generic;
+using System.Net;
+using System.Text;
+using System.Text.RegularExpressions;
+using HttpServer;
+using HttpServer.Headers;
+using Newtonsoft.Json;
+using HttpListener = HttpServer.HttpListener;
+
+namespace Rests
+{
+ ///
+ /// Rest command delegate
+ ///
+ /// Parameters in the url
+ /// {x} in urltemplate
+ /// Response object or null to not handle request
+ public delegate object RestCommandD(RestVerbs verbs, IParameterCollection parameters);
+ public class Rest : IDisposable
+ {
+ readonly List commands = new List();
+ HttpListener listener;
+ public IPAddress Ip { get; set; }
+ public int Port { get; set; }
+
+ public Rest(IPAddress ip, int port)
+ {
+ Ip = ip;
+ Port = port;
+ }
+ public virtual void Start()
+ {
+ if (listener == null)
+ {
+ listener = HttpListener.Create(Ip, Port);
+ listener.RequestReceived += OnRequest;
+ listener.Start(int.MaxValue);
+ }
+ }
+ public void Start(IPAddress ip, int port)
+ {
+ Ip = ip;
+ Port = port;
+ Start();
+ }
+ public virtual void Stop()
+ {
+ listener.Stop();
+ }
+
+ public void Register(string path, RestCommandD callback)
+ {
+ AddCommand(new RestCommand(path, callback));
+ }
+
+ public void Register(RestCommand com)
+ {
+ AddCommand(com);
+ }
+
+ protected void AddCommand(RestCommand com)
+ {
+ commands.Add(com);
+ }
+
+ protected virtual void OnRequest(object sender, RequestEventArgs e)
+ {
+ var obj = ProcessRequest(sender, e);
+ if (obj == null)
+ throw new NullReferenceException("obj");
+
+ var str = JsonConvert.SerializeObject(obj, Formatting.Indented);
+ e.Response.Connection.Type = ConnectionType.Close;
+ e.Response.Body.Write(Encoding.ASCII.GetBytes(str), 0, str.Length);
+ e.Response.Status = HttpStatusCode.OK;
+ return;
+ }
+
+ protected virtual object ProcessRequest(object sender, RequestEventArgs e)
+ {
+ var uri = e.Request.Uri.AbsolutePath;
+ uri = uri.TrimEnd('/');
+
+ foreach (var com in commands)
+ {
+ var verbs = new RestVerbs();
+ if (com.HasVerbs)
+ {
+ var match = Regex.Match(uri, com.UriVerbMatch);
+ if (!match.Success)
+ continue;
+ if ((match.Groups.Count - 1) != com.UriVerbs.Length)
+ continue;
+
+ for (int i = 0; i < com.UriVerbs.Length; i++)
+ verbs.Add(com.UriVerbs[i], match.Groups[i + 1].Value);
+ }
+ else if (com.UriTemplate.ToLower() != uri.ToLower())
+ {
+ continue;
+ }
+
+ var obj = ExecuteCommand(com, verbs, e.Request.Parameters);
+ if (obj != null)
+ return obj;
+
+ }
+ return new Dictionary { { "status", "404" }, { "error", "Specified API endpoint doesn't exist. Refer to the documentation for a list of valid endpoints." } };
+ }
+
+ protected virtual object ExecuteCommand(RestCommand cmd, RestVerbs verbs, IParameterCollection parms)
+ {
+ return cmd.Callback(verbs, parms);
+ }
+
+ #region Dispose
+ public void Dispose()
+ {
+ Dispose(true);
+ GC.SuppressFinalize(this);
+ }
+ protected virtual void Dispose(bool disposing)
+ {
+ if (disposing)
+ {
+ if (listener != null)
+ {
+ listener.Stop();
+ listener = null;
+ }
+ }
+ }
+ ~Rest()
+ {
+ Dispose(false);
+ }
+
+ #endregion
+ }
+}
diff --git a/TShockAPI/Rest/RestCommand.cs b/TShockAPI/Rest/RestCommand.cs
new file mode 100644
index 00000000..82ca22b1
--- /dev/null
+++ b/TShockAPI/Rest/RestCommand.cs
@@ -0,0 +1,47 @@
+using System.Linq;
+using System.Text.RegularExpressions;
+
+namespace Rests
+{
+ public class RestCommand
+ {
+ public string Name { get; protected set; }
+ public string UriTemplate { get; protected set; }
+ public string UriVerbMatch { get; protected set; }
+ public string[] UriVerbs { get; protected set; }
+ public RestCommandD Callback { get; protected set; }
+ public bool RequiesToken { get; set; }
+
+ ///
+ ///
+ ///
+ /// Used for identification
+ /// Url template
+ /// Rest Command callback
+ public RestCommand(string name, string uritemplate, RestCommandD callback)
+ {
+ Name = name;
+ UriTemplate = uritemplate;
+ UriVerbMatch = string.Format("^{0}$", string.Join("([^/]*)", Regex.Split(uritemplate, "\\{[^\\{\\}]*\\}")));
+ var matches = Regex.Matches(uritemplate, "\\{([^\\{\\}]*)\\}");
+ UriVerbs = (from Match match in matches select match.Groups[1].Value).ToArray();
+ Callback = callback;
+ RequiesToken = true;
+ }
+ ///
+ ///
+ ///
+ /// Url template
+ /// Rest Command callback
+ public RestCommand(string uritemplate, RestCommandD callback)
+ : this(string.Empty, uritemplate, callback)
+ {
+
+ }
+
+ public bool HasVerbs
+ {
+ get { return UriVerbs.Length > 0; }
+ }
+ }
+}
\ No newline at end of file
diff --git a/TShockAPI/Rest/RestManager.cs b/TShockAPI/Rest/RestManager.cs
new file mode 100644
index 00000000..2b6a1f48
--- /dev/null
+++ b/TShockAPI/Rest/RestManager.cs
@@ -0,0 +1,360 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using HttpServer;
+using Rests;
+using Terraria;
+
+namespace TShockAPI
+{
+
+ public class RestManager
+ {
+ private Rest Rest;
+ public RestManager(Rest rest)
+ {
+ Rest = rest;
+ }
+
+ public void RegisterRestfulCommands()
+ {
+ Rest.Register(new RestCommand("/status", Status) { RequiesToken = false });
+ Rest.Register(new RestCommand("/tokentest", TokenTest) { RequiesToken = true });
+
+ Rest.Register(new RestCommand("/users/read/{user}/info", UserInfo) { RequiesToken = true });
+ Rest.Register(new RestCommand("/users/destroy/{user}", UserDestroy) { RequiesToken = true });
+ Rest.Register(new RestCommand("/users/update/{user}", UserUpdate) { RequiesToken = true });
+
+ Rest.Register(new RestCommand("/bans/create", BanCreate) { RequiesToken = true });
+ Rest.Register(new RestCommand("/bans/read/{user}/info", BanInfo) { RequiesToken = true });
+ Rest.Register(new RestCommand("/bans/destroy/{user}", BanDestroy) { RequiesToken = true });
+
+
+ Rest.Register(new RestCommand("/lists/players", UserList) { RequiesToken = true });
+
+ Rest.Register(new RestCommand("/world/read", WorldRead) { RequiesToken = true });
+ Rest.Register(new RestCommand("/world/meteor", WorldMeteor) { RequiesToken = true });
+ Rest.Register(new RestCommand("/world/bloodmoon/{bool}", WorldBloodmoon) { RequiesToken = true });
+ //RegisterExamples();
+ }
+
+ #region RestMethods
+
+ object TokenTest(RestVerbs verbs, IParameterCollection parameters)
+ {
+ return new Dictionary { { "status", "200" }, { "response", "Token is valid and was passed through correctly." } };
+ }
+
+ object Status(RestVerbs verbs, IParameterCollection parameters)
+ {
+ if (TShock.Config.EnableTokenEndpointAuthentication)
+ return new RestObject("403") { Error = "Server settings require a token for this API call." };
+
+ var activeplayers = Main.player.Where(p => p != null && p.active).ToList();
+ string currentPlayers = string.Join(", ", activeplayers.Select(p => p.name));
+
+ var ret = new RestObject("200");
+ ret["name"] = TShock.Config.ServerNickname;
+ ret["port"] = Convert.ToString(TShock.Config.ServerPort);
+ ret["playercount"] = Convert.ToString(activeplayers.Count());
+ ret["players"] = currentPlayers;
+
+ return ret;
+ }
+
+ #endregion
+
+ #region RestUserMethods
+
+ object UserList(RestVerbs verbs, IParameterCollection parameters)
+ {
+ var activeplayers = Main.player.Where(p => p != null && p.active).ToList();
+ string currentPlayers = string.Join(", ", activeplayers.Select(p => p.name));
+ var ret = new RestObject("200");
+ ret["players"] = currentPlayers;
+ return ret;
+ }
+
+ object UserUpdate(RestVerbs verbs, IParameterCollection parameters)
+ {
+ var returnBlock = new Dictionary();
+ var password = parameters["password"];
+ var group = parameters["group"];
+
+ if (group == null && password == null)
+ {
+ returnBlock.Add("status", "400");
+ returnBlock.Add("error", "No parameters were passed.");
+ return returnBlock;
+ }
+
+ var user = TShock.Users.GetUserByName(verbs["user"]);
+ if (user == null)
+ {
+ returnBlock.Add("status", "400");
+ returnBlock.Add("error", "The specefied user doesn't exist.");
+ return returnBlock;
+ }
+
+ if (password != null)
+ {
+ TShock.Users.SetUserPassword(user, password);
+ returnBlock.Add("password-response", "Password updated successfully.");
+ }
+
+ if (group != null)
+ {
+ TShock.Users.SetUserGroup(user, group);
+ returnBlock.Add("group-response", "Group updated successfully.");
+ }
+
+ returnBlock.Add("status", "200");
+ return returnBlock;
+ }
+
+ object UserDestroy(RestVerbs verbs, IParameterCollection parameters)
+ {
+ var user = TShock.Users.GetUserByName(verbs["user"]);
+ if (user == null)
+ {
+ return new Dictionary { { "status", "400" }, { "error", "The specified user account does not exist." } };
+ }
+ var returnBlock = new Dictionary();
+ try
+ {
+ TShock.Users.RemoveUser(user);
+ }
+ catch (Exception)
+ {
+ returnBlock.Add("status", "400");
+ returnBlock.Add("error", "The specified user was unable to be removed.");
+ return returnBlock;
+ }
+ returnBlock.Add("status", "200");
+ returnBlock.Add("response", "User deleted successfully.");
+ return returnBlock;
+ }
+
+ object UserInfo(RestVerbs verbs, IParameterCollection parameters)
+ {
+ var user = TShock.Users.GetUserByName(verbs["user"]);
+ if (user == null)
+ {
+ return new Dictionary { { "status", "400" }, { "error", "The specified user account does not exist." } };
+ }
+
+ var returnBlock = new Dictionary();
+ returnBlock.Add("status", "200");
+ returnBlock.Add("group", user.Group);
+ returnBlock.Add("id", user.ID.ToString());
+ return returnBlock;
+ }
+
+ #endregion
+
+ #region RestBanMethods
+
+ object BanCreate(RestVerbs verbs, IParameterCollection parameters)
+ {
+ var returnBlock = new Dictionary();
+ var ip = parameters["ip"];
+ var name = parameters["name"];
+ var reason = parameters["reason"];
+
+ if (ip == null && name == null)
+ {
+ returnBlock.Add("status", "400");
+ returnBlock.Add("error", "Required parameters were missing from this API endpoint.");
+ return returnBlock;
+ }
+
+ if (ip == null)
+ {
+ ip = "";
+ }
+
+ if (name == null)
+ {
+ name = "";
+ }
+
+ if (reason == null)
+ {
+ reason = "";
+ }
+
+ try
+ {
+ TShock.Bans.AddBan(ip, name, reason);
+ }
+ catch (Exception)
+ {
+ returnBlock.Add("status", "400");
+ returnBlock.Add("error", "The specified ban was unable to be created.");
+ return returnBlock;
+ }
+ returnBlock.Add("status", "200");
+ returnBlock.Add("response", "Ban created successfully.");
+ return returnBlock;
+ }
+
+ object BanDestroy(RestVerbs verbs, IParameterCollection parameters)
+ {
+ var returnBlock = new Dictionary();
+
+ var type = parameters["type"];
+ if (type == null)
+ {
+ returnBlock.Add("Error", "Invalid Type");
+ return returnBlock;
+ }
+
+ var ban = new DB.Ban();
+ if (type == "ip") ban = TShock.Bans.GetBanByIp(verbs["user"]);
+ else if (type == "name") ban = TShock.Bans.GetBanByName(verbs["user"]);
+ else
+ {
+ returnBlock.Add("Error", "Invalid Type");
+ return returnBlock;
+ }
+
+ if (ban == null)
+ {
+ return new Dictionary { { "status", "400" }, { "error", "The specified ban does not exist." } };
+ }
+
+ try
+ {
+ TShock.Bans.RemoveBan(ban.IP);
+ }
+ catch (Exception)
+ {
+ returnBlock.Add("status", "400");
+ returnBlock.Add("error", "The specified ban was unable to be removed.");
+ return returnBlock;
+ }
+ returnBlock.Add("status", "200");
+ returnBlock.Add("response", "Ban deleted successfully.");
+ return returnBlock;
+ }
+
+ object BanInfo(RestVerbs verbs, IParameterCollection parameters)
+ {
+ var returnBlock = new Dictionary();
+
+ var type = parameters["type"];
+ if (type == null)
+ {
+ returnBlock.Add("Error", "Invalid Type");
+ return returnBlock;
+ }
+
+ var ban = new DB.Ban();
+ if (type == "ip") ban = TShock.Bans.GetBanByIp(verbs["user"]);
+ else if (type == "name") ban = TShock.Bans.GetBanByName(verbs["user"]);
+ else
+ {
+ returnBlock.Add("Error", "Invalid Type");
+ return returnBlock;
+ }
+
+ if (ban == null)
+ {
+ return new Dictionary { { "status", "400" }, { "error", "The specified ban does not exist." } };
+ }
+
+ returnBlock.Add("status", "200");
+ returnBlock.Add("name", ban.Name);
+ returnBlock.Add("ip", ban.IP);
+ returnBlock.Add("reason", ban.Reason);
+ return returnBlock;
+ }
+
+ #endregion
+
+ #region RestWorldMethods
+ object WorldRead(RestVerbs verbs, IParameterCollection parameters)
+ {
+ var returnBlock = new Dictionary();
+ returnBlock.Add("status", "200");
+ returnBlock.Add("name", Main.worldName);
+ returnBlock.Add("size", Main.maxTilesX + "*" + Main.maxTilesY);
+ returnBlock.Add("time", Main.time.ToString());
+ returnBlock.Add("daytime", Main.dayTime.ToString());
+ returnBlock.Add("bloodmoon", Main.bloodMoon.ToString());
+ returnBlock.Add("invasionsize", Main.invasionSize.ToString());
+ return returnBlock;
+ }
+
+ object WorldMeteor(RestVerbs verbs, IParameterCollection parameters)
+ {
+ WorldGen.dropMeteor();
+ var returnBlock = new Dictionary();
+ returnBlock.Add("status", "200");
+ returnBlock.Add("response", "Meteor has been spawned.");
+ return returnBlock;
+ }
+
+ object WorldBloodmoon(RestVerbs verbs, IParameterCollection parameters)
+ {
+ var returnBlock = new Dictionary();
+ var bloodmoonVerb = verbs["bool"];
+ bool bloodmoon;
+ if (bloodmoonVerb == null)
+ {
+ returnBlock.Add("status", "400");
+ returnBlock.Add("error", "No parameter was passed.");
+ return returnBlock;
+ }
+ if (!bool.TryParse(bloodmoonVerb, out bloodmoon))
+ {
+ returnBlock.Add("status", "400");
+ returnBlock.Add("error", "Unable to parse parameter.");
+ return returnBlock;
+ }
+ Main.bloodMoon = bloodmoon;
+ returnBlock.Add("status", "200");
+ returnBlock.Add("response", "Blood Moon has been set to " + bloodmoon.ToString());
+ return returnBlock;
+ }
+ #endregion
+
+ #region RestExampleMethods
+
+ public void RegisterExamples()
+ {
+ Rest.Register(new RestCommand("/HelloWorld/name/{username}", UserTest) { RequiesToken = false });
+ Rest.Register(new RestCommand("/wizard/{username}", Wizard) { RequiesToken = false });
+ }
+
+ //The Wizard example, for demonstrating the response convention:
+ object Wizard(RestVerbs verbs, IParameterCollection parameters)
+ {
+ var returnBack = new Dictionary();
+ returnBack.Add("status", "200"); //Keep this in everything, 200 = ok, etc. Standard http status codes.
+ returnBack.Add("error", "(If this failed, you would have a different status code and provide the error object.)"); //And only include this if the status isn't 200 or a failure
+ returnBack.Add("Verified Wizard", "You're a wizard, " + verbs["username"]); //Outline any api calls and possible responses in some form of documentation somewhere
+ return returnBack;
+ }
+
+ //http://127.0.0.1:8080/HelloWorld/name/{username}?type=status
+ object UserTest(RestVerbs verbs, IParameterCollection parameters)
+ {
+ var ret = new Dictionary();
+ var type = parameters["type"];
+ if (type == null)
+ {
+ ret.Add("Error", "Invalid Type");
+ return ret;
+ }
+ if (type == "status")
+ {
+ ret.Add("Users", "Info here");
+ return ret;
+ }
+ return null;
+ }
+ #endregion
+ }
+}
diff --git a/TShockAPI/Rest/RestObject.cs b/TShockAPI/Rest/RestObject.cs
new file mode 100644
index 00000000..fcc21e6a
--- /dev/null
+++ b/TShockAPI/Rest/RestObject.cs
@@ -0,0 +1,63 @@
+using System;
+using System.Collections.Generic;
+
+namespace Rests
+{
+ [Serializable]
+ public class RestObject : Dictionary
+ {
+ public string Status
+ {
+ get { return this["status"]; }
+ set { this["status"] = value; }
+ }
+ public string Error
+ {
+ get { return this["error"]; }
+ set { this["error"] = value; }
+ }
+ public string Response
+ {
+ get { return this["response"]; }
+ set { this["response"] = value; }
+ }
+
+ public RestObject(string status)
+ {
+ Status = status;
+ }
+
+ ///
+ /// Gets value safely, if it does not exist, return null. Sets/Adds value safely, if null it will remove.
+ ///
+ ///
+ ///
+ /// Returns null if key does not exist.
+ public new string this[string key]
+ {
+ get
+ {
+ string ret;
+ if (TryGetValue(key, out ret))
+ return ret;
+ return null;
+ }
+ set
+ {
+ if (!ContainsKey(key))
+ {
+ if (value == null)
+ return;
+ Add(key, value);
+ }
+ else
+ {
+ if (value != null)
+ base[key] = value;
+ else
+ Remove(key);
+ }
+ }
+ }
+ }
+}
\ No newline at end of file
diff --git a/TShockAPI/Rest/RestVerbs.cs b/TShockAPI/Rest/RestVerbs.cs
new file mode 100644
index 00000000..bbad41d3
--- /dev/null
+++ b/TShockAPI/Rest/RestVerbs.cs
@@ -0,0 +1,42 @@
+using System;
+using System.Collections.Generic;
+
+namespace Rests
+{
+ [Serializable]
+ public class RestVerbs : Dictionary
+ {
+ ///
+ /// Gets value safely, if it does not exist, return null. Sets/Adds value safely, if null it will remove.
+ ///
+ ///
+ ///
+ /// Returns null if key does not exist.
+ public new string this[string key]
+ {
+ get
+ {
+ string ret;
+ if (TryGetValue(key, out ret))
+ return ret;
+ return null;
+ }
+ set
+ {
+ if (!ContainsKey(key))
+ {
+ if (value == null)
+ return;
+ Add(key, value);
+ }
+ else
+ {
+ if (value != null)
+ base[key] = value;
+ else
+ Remove(key);
+ }
+ }
+ }
+ }
+}
\ No newline at end of file
diff --git a/TShockAPI/Rest/SecureRest.cs b/TShockAPI/Rest/SecureRest.cs
new file mode 100644
index 00000000..4d77c9b9
--- /dev/null
+++ b/TShockAPI/Rest/SecureRest.cs
@@ -0,0 +1,91 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Net;
+using System.Text;
+using HttpServer;
+using TShockAPI;
+
+namespace Rests
+{
+ ///
+ ///
+ ///
+ /// Username to verify
+ /// Password to verify
+ /// Returning a restobject with a null error means a successful verification.
+ public delegate RestObject VerifyD(string username, string password);
+ public class SecureRest : Rest
+ {
+ public Dictionary Tokens { get; protected set; }
+ public event VerifyD Verify;
+ public SecureRest(IPAddress ip, int port)
+ : base(ip, port)
+ {
+ Tokens = new Dictionary();
+ Register(new RestCommand("/token/create/{username}/{password}", NewToken) { RequiesToken = false });
+ Register(new RestCommand("/token/destroy/{token}", DestroyToken) { RequiesToken = true });
+ }
+
+ object DestroyToken(RestVerbs verbs, IParameterCollection parameters)
+ {
+ var token = verbs["token"];
+ try
+ {
+ Tokens.Remove(token);
+ }
+ catch (Exception)
+ {
+ return new Dictionary { { "status", "400" }, { "error", "The specified token queued for destruction failed to be deleted." } };
+ }
+ return new Dictionary { { "status", "200" }, { "response", "Requested token was successfully destroyed." } };
+ }
+
+ object NewToken(RestVerbs verbs, IParameterCollection parameters)
+ {
+ var user = verbs["username"];
+ var pass = verbs["password"];
+
+ RestObject obj = null;
+ if (Verify != null)
+ obj = Verify(user, pass);
+
+ if (obj == null)
+ obj = new RestObject("401") { Error = "Invalid username/password combination provided. Please re-submit your query with a correct pair." };
+
+ if (obj.Error != null)
+ return obj;
+
+ string hash;
+ var rand = new Random();
+ var randbytes = new byte[32];
+ do
+ {
+ rand.NextBytes(randbytes);
+ hash = randbytes.Aggregate("", (s, b) => s + b.ToString("X2"));
+ } while (Tokens.ContainsKey(hash));
+
+ Tokens.Add(hash, user);
+
+ obj["token"] = hash;
+ return obj;
+ }
+
+
+
+ protected override object ExecuteCommand(RestCommand cmd, RestVerbs verbs, IParameterCollection parms)
+ {
+ if (cmd.RequiesToken)
+ {
+ var strtoken = parms["token"];
+ if (strtoken == null)
+ return new Dictionary { { "status", "401" }, { "error", "Not authorized. The specified API endpoint requires a token." } };
+
+ object token;
+ if (!Tokens.TryGetValue(strtoken, out token))
+ return new Dictionary { { "status", "403" }, { "error", "Not authorized. The specified API endpoint requires a token, but the provided token was not valid." } };
+ }
+ return base.ExecuteCommand(cmd, verbs, parms);
+ }
+ }
+}
diff --git a/TShockAPI/TShock.cs b/TShockAPI/TShock.cs
index 89038817..bebb5e35 100644
--- a/TShockAPI/TShock.cs
+++ b/TShockAPI/TShock.cs
@@ -34,9 +34,12 @@ using System.IO;
using System.Net;
using System.Reflection;
using System.Linq;
+using System.Text.RegularExpressions;
using System.Threading;
using Community.CsharpSqlite.SQLiteClient;
+using HttpServer;
using MySql.Data.MySqlClient;
+using Rests;
using Terraria;
using TerrariaAPI;
using TerrariaAPI.Hooks;
@@ -67,6 +70,8 @@ namespace TShockAPI
public static bool OverridePort;
public static PacketBufferer PacketBuffer;
public static MaxMind.GeoIPCountry Geo;
+ public static SecureRest RestApi;
+ public static RestManager RestManager;
///
/// Called after TShock is initialized. Useful for plugins that needs hooks before tshock but also depend on tshock being loaded.
@@ -172,8 +177,15 @@ namespace TShockAPI
Regions = new RegionManager(DB);
Itembans = new ItemManager(DB);
RememberedPos = new RemeberedPosManager(DB);
- if (Config.EnableGeoIP)
- Geo = new MaxMind.GeoIPCountry(Path.Combine(SavePath, "GeoIP.dat"));
+ RestApi = new SecureRest(IPAddress.Any, 8080);
+ RestApi.Verify += RestApi_Verify;
+ RestApi.Port = Config.RestApiPort;
+ RestManager = new RestManager(RestApi);
+ RestManager.RegisterRestfulCommands();
+
+ var geoippath = Path.Combine(SavePath, "GeoIP.dat");
+ if (Config.EnableGeoIP && File.Exists(geoippath))
+ Geo = new MaxMind.GeoIPCountry(geoippath);
Log.ConsoleInfo(string.Format("TShock Version {0} ({1}) now running.", Version, VersionCodename));
@@ -209,6 +221,27 @@ namespace TShockAPI
}
}
+ RestObject RestApi_Verify(string username, string password)
+ {
+ var userAccount = TShock.Users.GetUserByName(username);
+ if (userAccount == null)
+ {
+ return new RestObject("401") { Error = "Invalid username/password combination provided. Please re-submit your query with a correct pair." };
+ }
+
+ if (Tools.HashPassword(password).ToUpper() != userAccount.Password.ToUpper())
+ {
+ return new RestObject("401") { Error = "Invalid username/password combination provided. Please re-submit your query with a correct pair." };
+ }
+
+ if (!Tools.GetGroup(userAccount.Group).HasPermission("api") && userAccount.Group != "superadmin")
+ {
+ return new RestObject("403") { Error = "Although your account was successfully found and identified, your account lacks the permission required to use the API. (api)" };
+ }
+
+ return new RestObject("200") { Response = "Successful login" }; //Maybe return some user info too?
+ }
+
public override void DeInitialize()
{
GameHooks.PostInitialize -= OnPostInit;
@@ -226,6 +259,7 @@ namespace TShockAPI
Console.WriteLine("Thanks for using TShock! Process ID file is now being destroyed.");
File.Delete(Path.Combine(SavePath, "tshock.pid"));
}
+ RestApi.Dispose();
//RconHandler.ShutdownAllThreads();
}
@@ -276,6 +310,7 @@ namespace TShockAPI
if (IPAddress.TryParse(parms[++i], out ip))
{
Netplay.serverListenIP = ip;
+ RestApi.Ip = ip;
Console.Write("Using IP: {0}", ip);
}
else
@@ -353,6 +388,8 @@ namespace TShockAPI
AuthToken = 0;
}
Regions.ReloadAllRegions();
+ if (Config.RestApiEnabled)
+ RestApi.Start();
}
@@ -625,7 +662,7 @@ namespace TShockAPI
NetMessage.SendData((int)PacketTypes.TimeSet, -1, -1, "", 0, 0, Main.sunModY, Main.moonModY);
NetMessage.syncPlayers();
- if (Config.EnableGeoIP)
+ if (Config.EnableGeoIP && Geo != null)
{
var code = Geo.TryGetCountryCode(IPAddress.Parse(player.IP));
player.Country = code == null ? "N/A" : MaxMind.GeoIPCountry.GetCountryNameByCode(code);
diff --git a/TShockAPI/TShockAPI.csproj b/TShockAPI/TShockAPI.csproj
index 523752e5..5a4d895b 100644
--- a/TShockAPI/TShockAPI.csproj
+++ b/TShockAPI/TShockAPI.csproj
@@ -52,6 +52,9 @@
False
..\SqlBins\Community.CsharpSqlite.SQLiteClient.dll
+
+ ..\HttpBins\HttpServer.dll
+
False
..\SqlBins\MySql.Data.dll
@@ -121,6 +124,12 @@
True
Resources.resx
+
+
+
+
+
+
@@ -177,7 +186,7 @@
-
+