0% found this document useful (0 votes)
60 views

SimpleHTTPServer in C# GitHub

Uploaded by

sestidavide.mail
Copyright
© © All Rights Reserved
Available Formats
Download as PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
60 views

SimpleHTTPServer in C# GitHub

Uploaded by

sestidavide.mail
Copyright
© © All Rights Reserved
Available Formats
Download as PDF, TXT or read online on Scribd
You are on page 1/ 10

2/5/2019 SimpleHTTPServer in C# · GitHub

Instantly share code, notes, and snippets.

aksakalli / SimpleHTTPServer.cs
Last active Apr 30, 2019

Embed <script src="https://gist. Download ZIP

SimpleHTTPServer in C#

SimpleHTTPServer.cs

1 // MIT License - Copyright (c) 2016 Can Güney Aksakalli


2 // https://aksakalli.github.io/2014/02/24/simple-http-server-with-csparp.html
3
4 using System;
5 using System.Collections.Generic;
6 using System.Linq;
7 using System.Text;
8 using System.Net.Sockets;
9 using System.Net;
10 using System.IO;
11 using System.Threading;
12 using System.Diagnostics;
13
14
15 class SimpleHTTPServer
16 {
17 private readonly string[] _indexFiles = {
18 "index.html",
19 "index.htm",
20 "default.html",
21 "default.htm"
22 };
23
24 private static IDictionary<string, string> _mimeTypeMappings = new Dictionary<string, string>(StringComparer.InvariantCultureIgnoreCase
25 #region extension to MIME type list
26 {".asf", "video/x-ms-asf"},
27 {".asx", "video/x-ms-asf"},
28 {".avi", "video/x-msvideo"},
29 {".bin", "application/octet-stream"},
30 {".cco", "application/x-cocoa"},
31 {".crt", "application/x-x509-ca-cert"},
32 {".css", "text/css"},
33 {".deb", "application/octet-stream"},
34 {".der", "application/x-x509-ca-cert"},
35 {".dll", "application/octet-stream"},
36 {".dmg", "application/octet-stream"},
37 {".ear", "application/java-archive"},
38 {".eot", "application/octet-stream"},
39 {".exe", "application/octet-stream"},
40 {".flv", "video/x-flv"},
41 {".gif", "image/gif"},
42 {".hqx", "application/mac-binhex40"},
43 {".htc", "text/x-component"},
44 {".htm", "text/html"},
45 {".html", "text/html"},
46 {".ico", "image/x-icon"},
47 {".img", "application/octet-stream"},
48 {".iso", "application/octet-stream"},
49 {".jar", "application/java-archive"},
50 {".jardiff", "application/x-java-archive-diff"},
51 {".jng", "image/x-jng"},
52 {".jnlp", "application/x-java-jnlp-file"},
53 {".jpeg", "image/jpeg"},
54 {".jpg", "image/jpeg"},
55 {".js", "application/x-javascript"},
56 {".mml", "text/mathml"},
57 {".mng", "video/x-mng"},
58 {".mov", "video/quicktime"},
59 {".mp3", "audio/mpeg"},
60 {".mpeg", "video/mpeg"},

https://gist.github.com/aksakalli/9191056 1/10
2/5/2019 SimpleHTTPServer in C# · GitHub
61 {".mpg", "video/mpeg"},
62 {".msi", "application/octet-stream"},
63 {".msm", "application/octet-stream"},
64 {".msp", "application/octet-stream"},
65 {".pdb", "application/x-pilot"},
66 {".pdf", "application/pdf"},
67 {".pem", "application/x-x509-ca-cert"},
68 {".pl", "application/x-perl"},
69 {".pm", "application/x-perl"},
70 {".png", "image/png"},
71 {".prc", "application/x-pilot"},
72 {".ra", "audio/x-realaudio"},
73 {".rar", "application/x-rar-compressed"},
74 {".rpm", "application/x-redhat-package-manager"},
75 {".rss", "text/xml"},
76 {".run", "application/x-makeself"},
77 {".sea", "application/x-sea"},
78 {".shtml", "text/html"},
79 {".sit", "application/x-stuffit"},
80 {".swf", "application/x-shockwave-flash"},
81 {".tcl", "application/x-tcl"},
82 {".tk", "application/x-tcl"},
83 {".txt", "text/plain"},
84 {".war", "application/java-archive"},
85 {".wbmp", "image/vnd.wap.wbmp"},
86 {".wmv", "video/x-ms-wmv"},
87 {".xml", "text/xml"},
88 {".xpi", "application/x-xpinstall"},
89 {".zip", "application/zip"},
90 #endregion
91 };
92 private Thread _serverThread;
93 private string _rootDirectory;
94 private HttpListener _listener;
95 private int _port;
96
97 public int Port
98 {
99 get { return _port; }
100 private set { }
101 }
102
103 /// <summary>
104 /// Construct server with given port.
105 /// </summary>
106 /// <param name="path">Directory path to serve.</param>
107 /// <param name="port">Port of the server.</param>
108 public SimpleHTTPServer(string path, int port)
109 {
110 this.Initialize(path, port);
111 }
112
113 /// <summary>
114 /// Construct server with suitable port.
115 /// </summary>
116 /// <param name="path">Directory path to serve.</param>
117 public SimpleHTTPServer(string path)
118 {
119 //get an empty port
120 TcpListener l = new TcpListener(IPAddress.Loopback, 0);
121 l.Start();
122 int port = ((IPEndPoint)l.LocalEndpoint).Port;
123 l.Stop();
124 this.Initialize(path, port);
125 }
126
127 /// <summary>
128 /// Stop server and dispose all functions.
129 /// </summary>
130 public void Stop()
131 {
132 _serverThread.Abort();
133 _listener.Stop();

https://gist.github.com/aksakalli/9191056 2/10
2/5/2019 SimpleHTTPServer in C# · GitHub
134 }
135
136 private void Listen()
137 {
138 _listener = new HttpListener();
139 _listener.Prefixes.Add("http://*:" + _port.ToString() + "/");
140 _listener.Start();
141 while (true)
142 {
143 try
144 {
145 HttpListenerContext context = _listener.GetContext();
146 Process(context);
147 }
148 catch (Exception ex)
149 {
150
151 }
152 }
153 }
154
155 private void Process(HttpListenerContext context)
156 {
157 string filename = context.Request.Url.AbsolutePath;
158 Console.WriteLine(filename);
159 filename = filename.Substring(1);
160
161 if (string.IsNullOrEmpty(filename))
162 {
163 foreach (string indexFile in _indexFiles)
164 {
165 if (File.Exists(Path.Combine(_rootDirectory, indexFile)))
166 {
167 filename = indexFile;
168 break;
169 }
170 }
171 }
172
173 filename = Path.Combine(_rootDirectory, filename);
174
175 if (File.Exists(filename))
176 {
177 try
178 {
179 Stream input = new FileStream(filename, FileMode.Open);
180
181 //Adding permanent http response headers
182 string mime;
183 context.Response.ContentType = _mimeTypeMappings.TryGetValue(Path.GetExtension(filename), out mime) ? mime : "application/o
184 context.Response.ContentLength64 = input.Length;
185 context.Response.AddHeader("Date", DateTime.Now.ToString("r"));
186 context.Response.AddHeader("Last-Modified", System.IO.File.GetLastWriteTime(filename).ToString("r"));
187
188 byte[] buffer = new byte[1024 * 16];
189 int nbytes;
190 while ((nbytes = input.Read(buffer, 0, buffer.Length)) > 0)
191 context.Response.OutputStream.Write(buffer, 0, nbytes);
192 input.Close();
193
194 context.Response.StatusCode = (int)HttpStatusCode.OK;
195 context.Response.OutputStream.Flush();
196 }
197 catch (Exception ex)
198 {
199 context.Response.StatusCode = (int)HttpStatusCode.InternalServerError;
200 }
201
202 }
203 else
204 {
205 context.Response.StatusCode = (int)HttpStatusCode.NotFound;
206 }

https://gist.github.com/aksakalli/9191056 3/10
2/5/2019 SimpleHTTPServer in C# · GitHub
207
208 context.Response.OutputStream.Close();
209 }
210
211 private void Initialize(string path, int port)
212 {
213 this._rootDirectory = path;
214 this._port = port;
215 _serverThread = new Thread(this.Listen);
216 _serverThread.Start();
217 }
218
219
220 }

aksakalli commented Feb 24, 2014 • edited Author Owner

If you need to run a quick web server and you don't want to mess with setting up IIS or something then this simple class allows you to serve
your static files on .Net Client Profile. It is a simple class that uses HttpListener Class and acts like SimpleHTTPServer of Python. It serves given
path on specified port or auto assigned empty port.

Create server with auto assigned port:

string myFolder = @"C:\folderpath\to\serve";

//create server with auto assigned port


SimpleHTTPServer myServer = new SimpleHTTPServer(myFolder);

Create server with specified port:

//create server with given port


SimpleHTTPServer myServer = new SimpleHTTPServer(myFolder, 8084);

Now it is running.

Console.WriteLine("Server is running on this port: " + myServer.Port.ToString());

Stop method should be called before exit.

//stop server
myServer.Stop();

Check the blog post for detailed explanation

ddoubleday commented Oct 2, 2015

Nice. One thing I noticed: you have to set the OK status for the response before you flush the output stream or you get a server internal error.
(Line 192)

Sotam commented Nov 5, 2015

Thanks for the awesome code! I've changed a single line, otherwise I couldn't stop the application/thread.

Find this:

_serverThread = new Thread(this.Listen);


_serverThread.Start();

And add between:

_serverThread.IsBackground = true;

https://gist.github.com/aksakalli/9191056 4/10
2/5/2019 SimpleHTTPServer in C# · GitHub
Not really sure if thats necessary, however it fixed my problem of not being able to close the application.

ghost commented Nov 28, 2015

https://github.com/cloudkitsch/nMVC
https://github.com/cloudkitsch/nMVC/blob/master/nMVC/Core%20Classes/HTTPServer.cs

ghost commented Nov 28, 2015

Usage https://github.com/cloudkitsch/nMVC/blob/master/SampleProject/WebApplication.cs#L52

nobodyguy commented Jan 6, 2016

Cool, thanks a lot! How can I wait until HTTPListener is really started to show MessageBox with text like "HTTP server was succesfully started on
port 80."?

raffomania commented Feb 24, 2016

I sometimes get the following error:

System.InvalidOperationException: Cannot be changed after headers are sent.


at System.Net.HttpListenerResponse.set_StatusCode (Int32 value)

Moving the line

context.Response.StatusCode = (int)HttpStatusCode.OK;

to the top when the headers are set fixes this, but I'm not sure if that's the right way...

aksakalli commented Mar 5, 2016 Author Owner

@ddoubleday , @raffomania you are right, I updated it. Thanks for your feedback.

@nobodyguy it is a synchronous method, you can show the port in the second line after SimpleHTTPServer myServer = new
SimpleHTTPServer(myFolder, 8084);

@Sotam have you tried to call myServer.Stop(); before closing your app?

dacrovinunghi commented Mar 30, 2016

should use "using" to close file stream if execption occurs.

dacrovinunghi commented Mar 30, 2016

not a big deal just : using(Stream input = new FileStream(filename, FileMode.Open)), will call dispose method

DanijelBumbar commented Apr 3, 2016

nice, thanks

Hulubulu123 commented Jun 4, 2016

I'm getting an error: An unhandled exception of type 'System.Net.HttpListenerException' occurred in System.dll Access is denied

https://gist.github.com/aksakalli/9191056 5/10
2/5/2019 SimpleHTTPServer in C# · GitHub
Please help!
P.S Otherwise great class and I look forward to using it in my application!

Anime4000 commented Jun 25, 2016

This need to be run under administrator to open a localhost port

Stormy102 commented Jul 6, 2016

I have a HTML page where we need to access a .xml and a .json file. However, they aren't loaded by the web server. Any ideas on why this isn't
working??

SnelleJelle commented Sep 17, 2016

Great snippet!

hadzim commented Oct 21, 2016

Take care of Path.Combine, if the second parameter is absolute path, it returns second parameter. So when I put something like:
http://localhost/C:/somefile.txt this implementation streams content of C:/somefile.txt without taking care, if this path is under specified
directory or not!!!

Joohae commented Nov 2, 2016 • edited

Thank you for sharing the code, it helps me a lot.

I got ProtocolViolationException on context.Response.OutputStream.Write(buffer, 0, nbytes); when I tried to download files with old version of
wget.

I found following article:


ProtocolViolationException when writing on response NetworkStream in c#

According to the article, we could get rid of the exception by not to send content when client requested header.
I have updated line 187 ~ 190 as followed:

if (context.Request.HttpMethod != "HEAD")
{
byte[] buffer = new byte[1024 * 16];
int nbytes;
while ((nbytes = input.Read(buffer, 0, buffer.Length)) > 0)
context.Response.OutputStream.Write(buffer, 0, nbytes);
}

aspartame21 commented Feb 2, 2017

@Hulubulu123, find line with _listener.Prefixes.Add("http://*:" + _port.ToString() + "/");


and change it to _listener.Prefixes.Add("http://127.0.0.1:" + _port.ToString() + "/");

wqweto commented Feb 12, 2017

https://gist.github.com/wqweto/f698cbe9ac8bfdbb3f300b0c4563f7e2 - the same with regex routing implementation in 174 LOC of C#. Includes
directory browsing "middleware" as a sample extension method.

Geograph-us commented Apr 15, 2017

What about HTTPS-support?

https://gist.github.com/aksakalli/9191056 6/10
2/5/2019 SimpleHTTPServer in C# · GitHub

zezba9000 commented Jun 18, 2017 • edited

Fixed memory leaks, Mono / Linux / macOS support issues and threading bugs.

https://gist.github.com/zezba9000/04054e3128e6af413e5bc8002489b2fe

Euler29 commented Jun 27, 2017

An unhandled exception of type 'System.Net.HttpListenerException' occurred in System.dll

Additional information:Access Denied.

I tried it run as be Administrator.I gave Safety Wall Permissions.But it didn't work.

muzack2 commented Jul 7, 2017

@Euler29, same problem, tried everything,

Anyone please?

therealpappy commented Jul 13, 2017

@Euler29 @muzack2

what you need to do is run your command prompt as an administrator. Then, use netsh http add urlacl url=http://+:80/ user=DOMAIN\user
Substitute 80 to whatever port you are using, DOMAIN to the name of your computer, and the second user to your windows user name.

Also change the asterisk on Line 138 to a + sign. You should be able to now run the server w/o an exception then go to localhost:port/path in
your browser and it will work.

San3131 commented Sep 15, 2017

I would like to run my server in 10.10.10.10 on default port 80 (10.10.10.10) or (10.10.10.10:80). But this line is throwing an exception.
httpListener.Prefixes.Add("http://10.10.10.10:" + "/"); How do I handle this.Also how do i connect with my server from my mobile at same time..

hunterbeanland commented Nov 16, 2017 • edited

Fixes needed:
Add {".mp4", "video/mpeg"} , to the MIME list.
To serve file with spaces, in Proceess, decode the URL: System.Web.HttpUtility.UrlDecode(filename.Substring(1));
You must use _listener.Prefixes.Add("http://127.0.0.1: or localhost to avoid Access Denied issues.

roschler commented Jan 3, 2018

If you don't know what to use for the "user=DOMAIN\user" parameter shown in the netsh command given by @therealpappy, you can use
"everyone" instead:

netsh http add urlacl url=http://+:80/ user=everyone

Note, everyone is language dependent so Spanish is "todos", German is 'alles", etc.

VBWebprofi commented Feb 9, 2018 • edited

It's a nice implementation, one point I would generally change - getting of the MIME-type. This should be done each time or on start at/from
Registry. Extensions there registered and MIME type is available most times from value Content Type (with space between both words). There
you can add also other MIME types or provide a static functionality at your class to add new custom MIME types to this you find on the
Registry. A dynamic solution would be to lookup at Registry on demand and store found in static dictionary. All other with no registered MIME
type should become application/octet-stream .

https://gist.github.com/aksakalli/9191056 7/10
2/5/2019 SimpleHTTPServer in C# · GitHub

movAX13h commented Jun 2, 2018

if you want to make sure videos (larger files) are working properly:
context.Response.SendChunked = input.Length > 1024 * 16;

movAX13h commented Jun 8, 2018 • edited

Note that this solution does not work if your website needs more than 1 concurrent request like it does if it streams a video and the user clicks
a link for example. The request following the click will not be processed because the server is busy serving the video. To solve this problem it is
necessary to process requests decoupled from the listener thread. Here it gets quite complicated. It has been done, for example:
https://github.com/JamesDunne/aardwolf

A very comfortable alternative solution (if you dont mind >200 dlls) which works in all cases is using Microsoft.AspNetCore (does not require
IIS): https://www.meziantou.net/2017/05/02/starting-a-http-file-server-from-the-file-explorer-using-net-core

ibrahimKafein commented Jun 11, 2018 • edited

Its simple and clear. Thanks... But how to resize request header length? How can I increase?

ricardo85x commented Jun 28, 2018

Is there a way to run this without administrator privileges?

xdvarpunen commented Jul 11, 2018 • edited

@ricardo85x Use these links:

https://stackoverflow.com/questions/4019466/httplistener-access-denied
https://docs.microsoft.com/en-us/dotnet/framework/wcf/feature-details/configuring-http-and-https
Basically use netsh -command to allow particular URL to particular user. Another option is to use localhost URL which is by default
allowed to everybody.

rodrigovitachi commented Jul 14, 2018

Any idea why JavaScript files are not working? Trying to load a html template with JQuery and other simple JS files, but they won't run.

Zlocoder commented Jul 21, 2018

What about https support?

smchughinfo commented Oct 30, 2018

This works for what I need. Thanks a lot.

ruicaramalho commented Nov 10, 2018

If you don't know what to use for the "user=DOMAIN\user" parameter shown in the netsh command given by @therealpappy, you can
use "everyone" instead:

netsh http add urlacl url=http://+:80/ user=everyone

Note, everyone is language dependent so Spanish is "todos", German is 'alles", etc.

Just do http add urlacl url=http://+:80/ sddl=D:(A;;GX;;;S-1-1-0)

sddl=D:(A;;GX;;;S-1-1-0) = "everyone" in all languages

https://gist.github.com/aksakalli/9191056 8/10
2/5/2019 SimpleHTTPServer in C# · GitHub

sjml commented Jan 29, 2019

I was trying this and noticed it was having trouble serving up multiple requests at a time. Turns out this line was throwing exceptions
occasionally for modifying the status code after headers were sent. I moved it up before anything was send to the output stream and things
started working more smoothly, but I wonder why it works sometimes if that's really as problematic as it looks.

atuladhar commented Feb 22, 2019

Hi, after creating a local server using the code above, I need to open a local file from that server. I have used the following code:

string myFolder = "D:\flower.jpg";


SimpleHTTPServer myServer = new SimpleHTTPServer(myFolder, 8084);

Now, when I try to access the link: http://localhost:8084/, the page isn't loaded. What needs to be done so that I can access the file in my path
from localhost?

prakis commented Feb 28, 2019

string myFolder = "D:\flower.jpg";


SimpleHTTPServer myServer = new SimpleHTTPServer(myFolder, 8084);

Your 'myFolder' variable is a file('..flower.jpg') not a folder.

kartoonist435 commented Mar 11, 2019

Hi all I'm using


public void StartServer() { myServer = new SimpleHTTPServer(Path.Combine(Application.streamingAssetsPath, "PDF"));
Application.OpenURL("http:/localhost:" + myServer.Port + "/" + FirstIndexPath); }
from this link https://answers.unity.com/questions/1245582/create-a-simple-https-server-on-the-streaming-asset.html

and I can't get anything to work. I keep getting localhost page can't be found. I've tried using html files pdfs and jpegs and nothing works. I
tried using a folder on the my android to house the pdfs at file:/// thinking it was a streaming asset Unity issue but that didn't help either. Any
help would be appreciated.

ulasaksan commented Mar 12, 2019

Hello, while using with .mp4 or .mpeg , video link starts to download mode, but i want it not download in browser, want it stream, can you show
how to do it?

Reza805 commented Apr 13, 2019

hi , how to get list of files in the directory?

aksakalli commented Apr 24, 2019 • edited Author Owner

@Reza805

for listing the files in the current directory as json, you can add a code block after line 159 like:

if (filename=="getfiles"){
files = System.IO.Directory.GetFiles(_rootDirectory, @"*", SearchOption.TopDirectoryOnly);
var serializer = new JavaScriptSerializer();
var jsonContent = serializer.Serialize(files);
context.Response.Write(jsonContent);
context.Response.StatusCode = (int)HttpStatusCode.OK;
return;
}

also add this to the top

using System.Web.Script.Serialization;

https://gist.github.com/aksakalli/9191056 9/10
2/5/2019 SimpleHTTPServer in C# · GitHub

Ps. I didn't run this snippet but it should work.

https://gist.github.com/aksakalli/9191056 10/10

You might also like