Coder Social home page Coder Social logo

nhttp's Introduction

NHttp

LGPL License.

Download from NuGet.

Introduction

NHttp is a simple asynchronous HTTP server written in C# for the .NET framework.

NHttp supports the following features:

  • Full request parsing similar to the ASP.net model;

  • High performance asynchronous request processing using TcpListener/TcpClient;

  • Complete query string parsing;

  • Complete form parsing (i.e. application/x-www-form-urlencoded);

  • Complete multi-part parsing including file upload (i.e. multipart/form-data);

  • Support for parsing and sending cookies.

NHttp specifically does not support any kind of utilities producing output. It for example does not provide a StreamWriter or perform routing. Besides e.g. the Headers and Cookies collections, only the raw output stream is provided. The rest is up to you!

Usage

The following shows how to use NHttp:

using (var server = new HttpServer())
{
    server.RequestReceived += (s, e) =>
    {
        using (var writer = new StreamWriter(e.Response.OutputStream))
        {
            writer.Write("Hello world!");
        }
    };

    server.Start();

    Process.Start(String.Format("http://{0}/", server.EndPoint));

    Console.WriteLine("Press any key to continue...");
    Console.ReadKey();
}

Processing requests in NHttp is done in the RequestReceived event. There you have access to the request and response information the request. The example above creates a StreamReader to be able to write text to the response and outputs the same response for every request.

By default, NHttp listens to a random port. Use the following method to specify the port NHttp should listen on:

using (var server = new HttpServer())
{
    // ...

    server.EndPoint = new IPEndPoint(IPAddress.Loopback, 80);

    server.Start();

    // ...
}

This method can also be used to change the interface the HttpServer should be listening to.

Logging

NHttp does not have a dependency on a logging framework, but uses Common.Logging if it's available. To enable logging, add a reference to Common.Logging (the version doesn't matter) to your project.

Bugs

Bugs should be reported through github at http://github.com/pvginkel/NHttp/issues.

License

NHttp is licensed under the LGPL 3.

nhttp's People

Contributors

jakubmacek avatar pvginkel avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

nhttp's Issues

Connected clients list and clients events

Hi Pieter, thanks for the good library (actually, this is the only one http server I've found on github, working without issues with UPnP/DLNA stack)!

Currently I'm working on simple DLNA-compatible media renderer for PC (it works like a built-in to smart TV media renderer). Normally, clients send DLNA "stop" action by existing/stopping work with the renderer but I definitely need to track disconnected clients/sessions in case of abnormal client completion (no "stop" action was sent), to hide media window.

Could you please add this functionality?

P.S. Found small issue (it's definitely not your fault but can be improved):
in HttpRequest.cs, line 120. Code below
ContentEncoding = Encoding.GetEncoding(encoding[1]);
can throw an exception if charset attribute will be equal '*' or "utf-8" (with quotes); these values are legitimate according to RFC 7231, page 8. The best fix is:

  • remove possible quotes from encoding[1]
  • replace wildcard (if any) to utf-8
  • add try/catch statement and process possible exception as utf-8 content encoding

Can't load Nttp in project with .net framework 4.0

I have a project in .net framework 4.5 but for requirements this is neccesary in .net framework 4.0.

Now when I change to this version of the framework can't load the NHttp.dll appear this message

Unable to load the file or assembly 'NHttp, Version = 0.1.9.0, Culture = neutral, PublicKeyToken = 156364e4f7b202d9' or one of its dependencies. An attempt was made to load a program with an incorrect format.

AcceptClientTcpCallback should always call EndAcceptTcpClient

Unless I am misunderstanding the flow here, AcceptClientTcpCallback will fail to make EndAcceptTcpClient calls to match the BeginAccept... calls once shutdown has been initiated. This is a bad thing, and could cause issues theoretically in a long running program. (Although practically I would imagine this mostly happens at shutdown.)

How can enable cross origin using nHttp

Hi we are using the project and with own request this work correctly, now when start the server and call a function from another page appear error of cross origin.

The library have the property of enable the cross origin for the request?

1

Also try this form, but not sure if is correctly:

e.Response.ContentType = "application/json"; e.Response.Headers.Add("Access-Control-Allow-Origin", "*"); e.Response.Headers.Add("Access-Control-Allow-Methods", "GET, POST"); e.Response.Headers.Add("Access-Control-Allow-Headers", "Content-Type");

Server silently crashes occasionally

From time to time, server stops responding to any requests. When this happens, there are no active threads related to NHttp.

Here is an example log:

5:48:13 HttpServer Starting HTTP server at 127.0.0.1:12345
5:48:13 HttpServer HTTP server running at 127.0.0.1:12345
5:48:14 HttpClient BeginRead failed
5:48:14 HttpServer Failed to accept TCP client
5:48:15 HttpClient Accepted request '...'
<~20 Accepted request messages>
5:52:08 HttpClient Accepted request '...'
5:52:18 HttpClient Accepted request '...'
5:52:29 HttpClient Accepted request '...'
5:52:39 HttpClient Accepted request '...'
5:52:39 HttpClient Failed to read from the HTTP connection

After that, no further request are accepted by the server and they all timeout on the client side.

Here is a dump of HttpServer properties from debugger at that time. _listner field is expanded:

  •   httpServer  {NHttp.HttpServer}  NHttp.HttpServer
    
  •   _clients    Count = 0   System.Collections.Generic.Dictionary<NHttp.HttpClient,bool>
    
  •   _clientsChangedEvent    {System.Threading.AutoResetEvent}   System.Threading.AutoResetEvent
    _disposed   false   bool
    
  •   _listener   {System.Net.Sockets.TcpListener}    System.Net.Sockets.TcpListener
    Active  true    bool
    ExclusiveAddressUse false   bool
    
  •   LocalEndpoint   {127.0.0.1:29235}   System.Net.EndPoint {System.Net.IPEndPoint}
    m_Active    true    bool
    m_ExclusiveAddressUse   false   bool
    
  •   m_ServerSocket  {System.Net.Sockets.Socket} System.Net.Sockets.Socket
    
  •   m_ServerSocketEP    {127.0.0.1:12345}   System.Net.IPEndPoint
    
  •   Server  {System.Net.Sockets.Socket} System.Net.Sockets.Socket
    addressFamily   InterNetwork    System.Net.Sockets.AddressFamily
    AddressFamily   InterNetwork    System.Net.Sockets.AddressFamily
    Available   0   int
    Blocking    true    bool
    
  •   Caches  {System.Net.Sockets.Socket.CacheSet}    System.Net.Sockets.Socket.CacheSet
    CanUseAcceptEx  false   bool
    CleanedUp   false   bool
    Connected   false   bool
    DontFragment    true    bool
    
  •   DualMode    'httpServer._listener.Server.DualMode' threw an exception of type 'System.NotSupportedException'    bool {System.NotSupportedException}
    
  •   EnableBroadcast 'httpServer._listener.Server.EnableBroadcast' threw an exception of type 'System.Net.Sockets.SocketException'   bool {System.Net.Sockets.SocketException}
    ExclusiveAddressUse false   bool
    
  •   Handle  3652    System.IntPtr
    IsBound true    bool
    IsDualMode  false   bool
    isListening true    bool
    
  •   LingerState {System.Net.Sockets.LingerOption}   System.Net.Sockets.LingerOption
    
  •   LocalEndPoint   {127.0.0.1:12345}   System.Net.EndPoint {System.Net.IPEndPoint}
    
  •   m_AcceptQueueOrConnectResult    Count = 0   object {System.Collections.Queue}
    
  •   m_AsyncEvent    {System.Threading.ManualResetEvent} System.Threading.ManualResetEvent
    m_BlockEventBits    FdAccept    System.Net.Sockets.AsyncEventBits
    m_BoundToThreadPool true    bool
    
  •   m_Caches    {System.Net.Sockets.Socket.CacheSet}    System.Net.Sockets.Socket.CacheSet
    m_CloseTimeout  -1  int
    
  •   m_DynamicWinsockMethods {System.Net.Sockets.DynamicWinsockMethods}  System.Net.Sockets.DynamicWinsockMethods
    
  •   m_Handle    {System.Net.SafeCloseSocket}    System.Net.SafeCloseSocket
    m_IntCleanedUp  0   int
    m_IsConnected   false   bool
    m_IsDisconnected    false   bool
    m_NonBlockingConnectInProgress  false   bool
    m_NonBlockingConnectRightEndPoint   null    System.Net.EndPoint
    
  •   m_PermittedRemoteAddress    null    System.Net.SocketAddress
    m_ReceivingPacketInformation    false   bool
    m_RegisteredWait    null    System.Threading.RegisteredWaitHandle
    m_RemoteEndPoint    null    System.Net.EndPoint
    
  •   m_RightEndPoint {127.0.0.1:12345}   System.Net.EndPoint {System.Net.IPEndPoint}
    
  •   MulticastLoopback   'httpServer._listener.Server.MulticastLoopback' threw an exception of type 'System.Net.Sockets.SocketException' bool {System.Net.Sockets.SocketException}
    NoDelay false   bool
    ProtocolType    Tcp System.Net.Sockets.ProtocolType
    protocolType    Tcp System.Net.Sockets.ProtocolType
    ReceiveBufferSize   8192    int
    ReceiveTimeout  0   int
    
  •   RemoteEndPoint  'httpServer._listener.Server.RemoteEndPoint' threw an exception of type 'System.Net.Sockets.SocketException'    System.Net.EndPoint {System.Net.Sockets.SocketException}
    
  •   SafeHandle  {System.Net.SafeCloseSocket}    System.Net.SafeCloseSocket
    SendBufferSize  8192    int
    SendTimeout 0   int
    SocketType  Stream  System.Net.Sockets.SocketType
    socketType  Stream  System.Net.Sockets.SocketType
    Transport   Tcp System.Net.TransportType
    Ttl 64  short
    UseOnlyOverlappedIO false   bool
    useOverlappedIO false   bool
    willBlock   true    bool
    willBlockInternal   true    bool
    
  •   Static members  
    _state  Started NHttp.HttpServerState
    _syncLock   {object}    object
    
  •   EndPoint    {127.0.0.1:12345}   System.Net.IPEndPoint
    
  •   base    {127.0.0.1:12345}   System.Net.EndPoint {System.Net.IPEndPoint}
    
  •   Address {127.0.0.1} System.Net.IPAddress
    AddressFamily   InterNetwork    System.Net.Sockets.AddressFamily
    
  •   m_Address   {127.0.0.1} System.Net.IPAddress
    m_Port  12345   int
    Port    12345   int
    
  •   Static members  
    ReadBufferSize  4096    int
    
  •   RequestReceived {Method = {Void <Start>b__0(System.Object, NHttp.HttpRequestEventArgs)}}    NHttp.HttpRequestEventHandler
    
  •   base    {Method = {Void <Start>b__0(System.Object, NHttp.HttpRequestEventArgs)}}    System.MulticastDelegate {NHttp.HttpRequestEventHandler}
    
  •   base    {Method = {Void <Start>b__0(System.Object, NHttp.HttpRequestEventArgs)}}    System.Delegate {NHttp.HttpRequestEventHandler}
    
  •   _invocationCount    0   System.IntPtr
    _invocationList null    object
    ServerBanner    "NHttp/0.1.7.0" string
    
  •   ServerUtility   {NHttp.HttpServerUtility}   NHttp.HttpServerUtility
    
  •   ShutdownTimeout {00:00:30}  System.TimeSpan
    State   Started NHttp.HttpServerState
    StateChanged    null    System.EventHandler
    UnhandledException  null    NHttp.HttpExceptionEventHandler
    WriteBufferSize 4096    int
    

Is there a way to get TcpClient or Socket from request?

Hello,
I would like to use NHttp for Selenium WebDriver implementation, which is basically a REST service.
But to provide responses I will first need to call remote procedure on app under a test, which I want to do using JSON RPC over dual web socket communication, so the server needs to be able to accept a socket connection and save it for future message dispatching.

Is it possible in NHttp? HttpRequestEventArgs does not seems to contain such data.

System.TypeInitializationException When Common.Logging is not avaliable

Hello,

When using NHttp on my project or on your own i get this error when the Common.Logging is not referenced:

An unhandled exception of type 'System.TypeInitializationException' occurred in NHttp.Demo.exe

            StackTrace:
                 em System.Reflection.RuntimeAssembly._nLoad(AssemblyName fileName, String codeBase, Evidence assemblySecurity, RuntimeAssembly locationHint, StackCrawlMark& stackMark, IntPtr pPrivHostBinder, Boolean throwOnFileNotFound, Boolean forIntrospection, Boolean suppressSecurityChecks)
                 em System.Reflection.RuntimeAssembly.nLoad(AssemblyName fileName, String codeBase, Evidence assemblySecurity, RuntimeAssembly locationHint, StackCrawlMark& stackMark, IntPtr pPrivHostBinder, Boolean throwOnFileNotFound, Boolean forIntrospection, Boolean suppressSecurityChecks)
                 em System.Reflection.RuntimeAssembly.InternalLoadAssemblyName(AssemblyName assemblyRef, Evidence assemblySecurity, RuntimeAssembly reqAssembly, StackCrawlMark& stackMark, IntPtr pPrivHostBinder, Boolean throwOnFileNotFound, Boolean forIntrospection, Boolean suppressSecurityChecks)
                 em System.Reflection.RuntimeAssembly.InternalLoad(String assemblyString, Evidence assemblySecurity, StackCrawlMark& stackMark, IntPtr pPrivHostBinder, Boolean forIntrospection)
                 em System.Reflection.RuntimeAssembly.InternalLoad(String assemblyString, Evidence assemblySecurity, StackCrawlMark& stackMark, Boolean forIntrospection)
                 em System.Reflection.Assembly.Load(String assemblyString)
                 em NHttp.LogManager..cctor() em d:\Tiago\Desktop\NHttp-master\NHttp\LogManager.cs:line 22
            InnerException: 

The way i found to fix it its editing your code on LogManager constructor and add the try/cath:

           Assembly assembly;
            try
            {
                assembly = Assembly.Load("Common.Logging");
                if (assembly == null)
                    return;
            }
            catch
            {
                return;
            }

Renember that Assemly.Load can trown exceptions. (https://msdn.microsoft.com/en-us/library/ky3942xh(v=vs.110).aspx)
Also its possible to do some basic auth like http auth when accesing to the server url?

Thanks for the great library!

Chrome Browser processes a single request twice!

There seem to be an issue with Chrome browser. Requests made with Chrome browser is processed twice in the Request Received event for every single request.
The first processing is the valid one. The second processing is not valid - gives error "Object reference not set to an instance of an object"

Other browsers processes the request just once.

See code snippet below.

Private Sub OnWebRequestReceived(sender As Object, e As HttpRequestEventArgs)

    kknntt += 1

    Dim sMobileNo, sMessageTxt, sSenderID, sSourceToken, ret As String

    Using Response = New StreamWriter(e.Response.OutputStream)

        Try
            sMobileNo = e.Request.QueryString.GetValues("mobileno").GetValue(0)
            sMessageTxt = e.Request.QueryString.GetValues("messagetext").GetValue(0)
            sSenderID = e.Request.QueryString.GetValues("senderid").GetValue(0)
            sSourceToken = e.Request.QueryString.GetValues("token").GetValue(0)
            ret = "OK"
            Response.Write(ret)
        Catch ex As Exception
            ret = "[HTTPWebService Error] - " & ex.Message & Environment.NewLine & ex.StackTrace
            EventLogger.WriteEntry(ret, EventLogEntryType.Error)
            MessageLog(ret, "APPLICATION.ERROR")
            Response.Write(String.Format("{0}#ERROR#{1}", sMobileNo, "Unable to process."))
        End Try
    End Using
    MessageLog(kknntt.ToString & " - " & ret)
End Sub`

Add support for .NET Core Framework

Your embedded server is a really nice tool especially for integration testing. It would be very useful if you had a version compiled targeting the new .NET Core framework.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.