Repository files navigation

webserver

A zero dependency Python 3 web server to echo back an HTTP request's headers and data.

Why?

I found myself developing a web app that sends out a webhook when a specific event occurs. I wanted a quick and painless way to set up a local server to make sure my web app was correctly sending out the webhook.

I mainly wanted to verify if it was sending the correct headers and data, so here we are.

Installation

If you're using my dotfiles, it comes pre-installed by default!

All you have to do is download the webserver script, make sure it's executable and place it somewhere on your system path.

1 liner to get webserver downloaded to /usr/local/bin:

sudo curl \
-L https://raw.githubusercontent.com/nickjj/webserver/v0.4.2/webserver \
-o /usr/local/bin/webserver && sudo chmod +x /usr/local/bin/webserver

That will download the latest release. If you want to download the bleeding edge version you can replace the version number with master to download it from the master branch.

Alternatively it's available in a Docker image:

This could be useful if you want this process to run on the same network as your other Docker containers.

docker container run -it -p 127.0.0.1:8008:8008 nickjj/webserver:v0.4.2

If you go this route, you can run the above command instead of webserver when following the docs below.

Usage

You can start the server by running webserver.

If you're not using Docker, that will listen on http://localhost:8008 by default. You can customize the bind address and port by running it with webserver 0.0.0.0:5000 or any host:port you want.

You can hit CTRL+C to stop the server.

Testing it out with curl

With your webserver running, now you can send requests to it however you see fit.

# Send a GET request with a query string.
curl localhost:8008/?just=testing
# Response (empty body):
127.0.0.1 - - [09/Sep/2020 14:23:24] "GET /?just=testing HTTP/1.1" 200 -
Host: localhost:8008
User-Agent: curl/7.68.0
Accept: */*
# Send a POST request with inline JSON data. You can use PUT, PATCH and DELETE too.
curl localhost:8008/ \
-H "Content-Type: application/json" \
-X POST --data '{"foo":"bar"}'# Response:
127.0.0.1 - - [09/Sep/2020 14:09:33] "POST / HTTP/1.1" 200 -
Host: localhost:8008
User-Agent: curl/7.68.0
Accept: */*
Content-Type: application/json
Content-Length: 13
{"foo":"bar"}
# Send a POST request with file based JSON data.echo'{"hello":"world"}'> test.json
curl localhost:8008/ \
-H "Content-Type: application/json" \
-X POST --data @test.json
# Response:
127.0.0.1 - - [09/Sep/2020 14:10:06] "POST / HTTP/1.1" 200 -
Host: localhost:8008
User-Agent: curl/7.68.0
Accept: */*
Content-Type: application/json
Content-Length: 17
{"hello":"world"}
# Send a POST request with form data.
curl localhost:8008/ \
-H "Content-Type: application/x-www-form-urlencoded" \
-X POST --data "foo=bar"# Response:
127.0.0.1 - - [09/Sep/2020 14:10:36] "POST / HTTP/1.1" 200 -
Host: localhost:8008
User-Agent: curl/7.68.0
Accept: */*
Content-Type: application/x-www-form-urlencoded
Content-Length: 7
foo=bar

If you had a Python application you could use the requests library to send requests instead of curl. Or feel free to use whatever HTTP client your programming language has available.

FAQ

What if your web app is running in Docker?

You have a few options.

Running the standalone webserver script without Docker?

You can run webserver 0.0.0.0:8008 and from within your container you can access it through host.docker.internal:8008 as long as you're using Docker Desktop.

If you're on native Linux without DD you can add this flag --add-host=host.docker.internal:host-gateway to your container's Docker command or if you're using Docker Compose you can add this property to your app's service extra_hosts: ["host.docker.internal:host-gateway"]. Now host.docker.internal will work.

Running webserver with Docker?

If everything is running in Docker Compose you can do:

services:
myapp:
# ...webserver:
image: "nickjj/webserver:v0.4.2"

From within your myapp container you'll be able to connect to webserver:8008. Basically you can access it over your container's network like usual, the same goes without using Docker Compose.

You can optionally add ports: ["127.0.0.1:8008:8008"] if you want to access the webserver locally on your Docker host with curl http://localhost:8008. In this case we're publishing the port back to your host.

What about exposing this server to the internet?

Sure. There's lots of tools you can use. One of them that's free is ngrok. No port forwarding needed!

After installing ngrok you can start your webserver and then run ngrok http 8008. A few seconds later you'll have a publicly accessible HTTPS version of this local server that you can access over the internet.

Keep in mind that's only practical for end to end tests, not a real production environment.

The above could be handy if you had a test server on the cloud that you've deployed your web app to and you wanted it to send a webhook response to your local webserver. You could configure your deployed web app to send the webhook to the ngrok address instead of localhost:8008.

Keep in mind if you're only dealing with local development you don't need to use ngrok at all.

About the Author

I'm a self taught developer and have been freelancing for the last ~20 years. You can read about everything I've learned along the way on my site at https://nickjanetakis.com. There's hundreds of blog posts and a couple of video courses on web development and deployment topics. I also have a podcast where I talk to folks about running web apps in production.

About

A zero dependency Python 3 web server to echo back an HTTP request's headers and data.

Resources

Stars

54 stars

Watchers

1 watching

Forks

Releases

Packages

Contributors

Languages

, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Add copy buttons to all
 blocks\n(function() {\n function addCopyButtons() {\n document.querySelectorAll('pre code').forEach(function(codeBlock) {\n if (codeBlock.parentElement.hasAttribute('data-copy-added')) return;\n codeBlock.parentElement.setAttribute('data-copy-added', 'true');\n \n var btn = document.createElement('button');\n btn.textContent = 'Copy';\n btn.style.cssText = 'position:absolute;top:4px;right:4px;padding:2px 8px;font-size:11px;background:#4ecdc4;border:none;border-radius:4px;color:#1a1a2e;cursor:pointer;opacity:0.7;transition:opacity 0.2s;';\n btn.onmouseover = function() { this.style.opacity = '1'; };\n btn.onmouseout = function() { this.style.opacity = '0.7'; };\n btn.onclick = function() {\n navigator.clipboard.writeText(codeBlock.textContent).then(function() {\n btn.textContent = 'Copied!';\n setTimeout(function() { btn.textContent = 'Copy'; }, 1500);\n });\n };\n codeBlock.parentElement.style.position = 'relative';\n codeBlock.parentElement.appendChild(btn);\n });\n }\n \n addCopyButtons();\n \n // Re-run on dynamic content\n var observer = new MutationObserver(addCopyButtons);\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "Add Copy Buttons to Code Blocks");
}
} catch(__e) { console.warn('[Userscript:Add Copy Buttons to Code Blocks]', __e); }
})();
(function(){
try {
var __m = "github.com";
var __re = new RegExp('^' + "github\\.com" + '
Skip to content

Repository files navigation

webserver

A zero dependency Python 3 web server to echo back an HTTP request's headers and data.

Why?

I found myself developing a web app that sends out a webhook when a specific event occurs. I wanted a quick and painless way to set up a local server to make sure my web app was correctly sending out the webhook.

I mainly wanted to verify if it was sending the correct headers and data, so here we are.

Installation

If you're using my dotfiles, it comes pre-installed by default!

All you have to do is download the webserver script, make sure it's executable and place it somewhere on your system path.

1 liner to get webserver downloaded to /usr/local/bin:

sudo curl \
-L https://raw.githubusercontent.com/nickjj/webserver/v0.4.2/webserver \
-o /usr/local/bin/webserver && sudo chmod +x /usr/local/bin/webserver

That will download the latest release. If you want to download the bleeding edge version you can replace the version number with master to download it from the master branch.

Alternatively it's available in a Docker image:

This could be useful if you want this process to run on the same network as your other Docker containers.

docker container run -it -p 127.0.0.1:8008:8008 nickjj/webserver:v0.4.2

If you go this route, you can run the above command instead of webserver when following the docs below.

Usage

You can start the server by running webserver.

If you're not using Docker, that will listen on http://localhost:8008 by default. You can customize the bind address and port by running it with webserver 0.0.0.0:5000 or any host:port you want.

You can hit CTRL+C to stop the server.

Testing it out with curl

With your webserver running, now you can send requests to it however you see fit.

# Send a GET request with a query string.
curl localhost:8008/?just=testing
# Response (empty body):
127.0.0.1 - - [09/Sep/2020 14:23:24] "GET /?just=testing HTTP/1.1" 200 -
Host: localhost:8008
User-Agent: curl/7.68.0
Accept: */*
# Send a POST request with inline JSON data. You can use PUT, PATCH and DELETE too.
curl localhost:8008/ \
-H "Content-Type: application/json" \
-X POST --data '{"foo":"bar"}'# Response:
127.0.0.1 - - [09/Sep/2020 14:09:33] "POST / HTTP/1.1" 200 -
Host: localhost:8008
User-Agent: curl/7.68.0
Accept: */*
Content-Type: application/json
Content-Length: 13
{"foo":"bar"}
# Send a POST request with file based JSON data.echo'{"hello":"world"}'> test.json
curl localhost:8008/ \
-H "Content-Type: application/json" \
-X POST --data @test.json
# Response:
127.0.0.1 - - [09/Sep/2020 14:10:06] "POST / HTTP/1.1" 200 -
Host: localhost:8008
User-Agent: curl/7.68.0
Accept: */*
Content-Type: application/json
Content-Length: 17
{"hello":"world"}
# Send a POST request with form data.
curl localhost:8008/ \
-H "Content-Type: application/x-www-form-urlencoded" \
-X POST --data "foo=bar"# Response:
127.0.0.1 - - [09/Sep/2020 14:10:36] "POST / HTTP/1.1" 200 -
Host: localhost:8008
User-Agent: curl/7.68.0
Accept: */*
Content-Type: application/x-www-form-urlencoded
Content-Length: 7
foo=bar

If you had a Python application you could use the requests library to send requests instead of curl. Or feel free to use whatever HTTP client your programming language has available.

FAQ

What if your web app is running in Docker?

You have a few options.

Running the standalone webserver script without Docker?

You can run webserver 0.0.0.0:8008 and from within your container you can access it through host.docker.internal:8008 as long as you're using Docker Desktop.

If you're on native Linux without DD you can add this flag --add-host=host.docker.internal:host-gateway to your container's Docker command or if you're using Docker Compose you can add this property to your app's service extra_hosts: ["host.docker.internal:host-gateway"]. Now host.docker.internal will work.

Running webserver with Docker?

If everything is running in Docker Compose you can do:

services:
myapp:
# ...webserver:
image: "nickjj/webserver:v0.4.2"

From within your myapp container you'll be able to connect to webserver:8008. Basically you can access it over your container's network like usual, the same goes without using Docker Compose.

You can optionally add ports: ["127.0.0.1:8008:8008"] if you want to access the webserver locally on your Docker host with curl http://localhost:8008. In this case we're publishing the port back to your host.

What about exposing this server to the internet?

Sure. There's lots of tools you can use. One of them that's free is ngrok. No port forwarding needed!

After installing ngrok you can start your webserver and then run ngrok http 8008. A few seconds later you'll have a publicly accessible HTTPS version of this local server that you can access over the internet.

Keep in mind that's only practical for end to end tests, not a real production environment.

The above could be handy if you had a test server on the cloud that you've deployed your web app to and you wanted it to send a webhook response to your local webserver. You could configure your deployed web app to send the webhook to the ngrok address instead of localhost:8008.

Keep in mind if you're only dealing with local development you don't need to use ngrok at all.

About the Author

I'm a self taught developer and have been freelancing for the last ~20 years. You can read about everything I've learned along the way on my site at https://nickjanetakis.com. There's hundreds of blog posts and a couple of video courses on web development and deployment topics. I also have a podcast where I talk to folks about running web apps in production.

About

A zero dependency Python 3 web server to echo back an HTTP request's headers and data.

Resources

Stars

54 stars

Watchers

1 watching

Forks

Releases

Packages

Contributors

Languages

, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Force GitHub README to respect dark mode\n(function() {\n var style = document.createElement('style');\n style.textContent = '\n .markdown-body {\n color-scheme: dark light;\n }\n .markdown-body pre { background: #161b22 !important; }\n .markdown-body code { background: rgba(110, 118, 129, 0.4) !important; }\n .markdown-body table th, .markdown-body table td { border-color: #30363d !important; }\n .markdown-body img { background: #0d1117; }\n .markdown-body blockquote { border-left-color: #8b949e; }\n .markdown-body hr { border-color: #30363d; }\n ';\n document.head.appendChild(style);\n})();", "GitHub Dark Mode README Fix"); } } catch(__e) { console.warn('[Userscript:GitHub Dark Mode README Fix]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content

Repository files navigation

webserver

A zero dependency Python 3 web server to echo back an HTTP request's headers and data.

Why?

I found myself developing a web app that sends out a webhook when a specific event occurs. I wanted a quick and painless way to set up a local server to make sure my web app was correctly sending out the webhook.

I mainly wanted to verify if it was sending the correct headers and data, so here we are.

Installation

If you're using my dotfiles, it comes pre-installed by default!

All you have to do is download the webserver script, make sure it's executable and place it somewhere on your system path.

1 liner to get webserver downloaded to /usr/local/bin:

sudo curl \
-L https://raw.githubusercontent.com/nickjj/webserver/v0.4.2/webserver \
-o /usr/local/bin/webserver && sudo chmod +x /usr/local/bin/webserver

That will download the latest release. If you want to download the bleeding edge version you can replace the version number with master to download it from the master branch.

Alternatively it's available in a Docker image:

This could be useful if you want this process to run on the same network as your other Docker containers.

docker container run -it -p 127.0.0.1:8008:8008 nickjj/webserver:v0.4.2

If you go this route, you can run the above command instead of webserver when following the docs below.

Usage

You can start the server by running webserver.

If you're not using Docker, that will listen on http://localhost:8008 by default. You can customize the bind address and port by running it with webserver 0.0.0.0:5000 or any host:port you want.

You can hit CTRL+C to stop the server.

Testing it out with curl

With your webserver running, now you can send requests to it however you see fit.

# Send a GET request with a query string.
curl localhost:8008/?just=testing
# Response (empty body):
127.0.0.1 - - [09/Sep/2020 14:23:24] "GET /?just=testing HTTP/1.1" 200 -
Host: localhost:8008
User-Agent: curl/7.68.0
Accept: */*
# Send a POST request with inline JSON data. You can use PUT, PATCH and DELETE too.
curl localhost:8008/ \
-H "Content-Type: application/json" \
-X POST --data '{"foo":"bar"}'# Response:
127.0.0.1 - - [09/Sep/2020 14:09:33] "POST / HTTP/1.1" 200 -
Host: localhost:8008
User-Agent: curl/7.68.0
Accept: */*
Content-Type: application/json
Content-Length: 13
{"foo":"bar"}
# Send a POST request with file based JSON data.echo'{"hello":"world"}'> test.json
curl localhost:8008/ \
-H "Content-Type: application/json" \
-X POST --data @test.json
# Response:
127.0.0.1 - - [09/Sep/2020 14:10:06] "POST / HTTP/1.1" 200 -
Host: localhost:8008
User-Agent: curl/7.68.0
Accept: */*
Content-Type: application/json
Content-Length: 17
{"hello":"world"}
# Send a POST request with form data.
curl localhost:8008/ \
-H "Content-Type: application/x-www-form-urlencoded" \
-X POST --data "foo=bar"# Response:
127.0.0.1 - - [09/Sep/2020 14:10:36] "POST / HTTP/1.1" 200 -
Host: localhost:8008
User-Agent: curl/7.68.0
Accept: */*
Content-Type: application/x-www-form-urlencoded
Content-Length: 7
foo=bar

If you had a Python application you could use the requests library to send requests instead of curl. Or feel free to use whatever HTTP client your programming language has available.

FAQ

What if your web app is running in Docker?

You have a few options.

Running the standalone webserver script without Docker?

You can run webserver 0.0.0.0:8008 and from within your container you can access it through host.docker.internal:8008 as long as you're using Docker Desktop.

If you're on native Linux without DD you can add this flag --add-host=host.docker.internal:host-gateway to your container's Docker command or if you're using Docker Compose you can add this property to your app's service extra_hosts: ["host.docker.internal:host-gateway"]. Now host.docker.internal will work.

Running webserver with Docker?

If everything is running in Docker Compose you can do:

services:
myapp:
# ...webserver:
image: "nickjj/webserver:v0.4.2"

From within your myapp container you'll be able to connect to webserver:8008. Basically you can access it over your container's network like usual, the same goes without using Docker Compose.

You can optionally add ports: ["127.0.0.1:8008:8008"] if you want to access the webserver locally on your Docker host with curl http://localhost:8008. In this case we're publishing the port back to your host.

What about exposing this server to the internet?

Sure. There's lots of tools you can use. One of them that's free is ngrok. No port forwarding needed!

After installing ngrok you can start your webserver and then run ngrok http 8008. A few seconds later you'll have a publicly accessible HTTPS version of this local server that you can access over the internet.

Keep in mind that's only practical for end to end tests, not a real production environment.

The above could be handy if you had a test server on the cloud that you've deployed your web app to and you wanted it to send a webhook response to your local webserver. You could configure your deployed web app to send the webhook to the ngrok address instead of localhost:8008.

Keep in mind if you're only dealing with local development you don't need to use ngrok at all.

About the Author

I'm a self taught developer and have been freelancing for the last ~20 years. You can read about everything I've learned along the way on my site at https://nickjanetakis.com. There's hundreds of blog posts and a couple of video courses on web development and deployment topics. I also have a podcast where I talk to folks about running web apps in production.

About

A zero dependency Python 3 web server to echo back an HTTP request's headers and data.

Resources

Stars

54 stars

Watchers

1 watching

Forks

Releases

Packages

Contributors

Languages

, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Highlight search terms from Google/DuckDuckGo/Bing referrer\n(function() {\n var ref = document.referrer;\n var terms = [];\n \n if (ref.includes('google.com') || ref.includes('duckduckgo.com') || ref.includes('bing.com')) {\n var url = new URL(ref);\n var q = url.searchParams.get('q') || url.searchParams.get('p');\n if (q) {\n terms = q.split(/\\s+/).filter(function(t) { return t.length > 2; });\n }\n }\n \n if (terms.length === 0) return;\n \n var style = document.createElement('style');\n style.textContent = '.userscript-highlight { background: #fbbf24; color: #1a1a2e; padding: 1px 3px; border-radius: 2px; }';\n document.head.appendChild(style);\n \n function highlight(node) {\n if (node.nodeType === 3) { // text node\n var text = node.textContent;\n var found = false;\n terms.forEach(function(term) {\n var regex = new RegExp('(' + term.replace(/[.*+?^${}()|[\\]\\\\]/g, '\\\\') + ')', 'gi');\n if (regex.test(text)) {\n found = true;\n var frag = document.createDocumentFragment();\n var parts = text.split(regex);\n parts.forEach(function(part, i) {\n if (i % 2 === 0) {\n frag.appendChild(document.createTextNode(part));\n } else {\n var span = document.createElement('span');\n span.className = 'userscript-highlight';\n span.textContent = part;\n frag.appendChild(span);\n }\n });\n node.parentNode.replaceChild(frag, node);\n }\n });\n } else if (node.nodeType === 1 && node.childNodes) { // element\n var skipTags = ['SCRIPT', 'STYLE', 'NOSCRIPT', 'TEXTAREA', 'INPUT', 'SELECT'];\n if (!skipTags.includes(node.tagName)) {\n Array.from(node.childNodes).forEach(highlight);\n }\n }\n }\n \n highlight(document.body);\n \n // Re-highlight on dynamic content\n var observer = new MutationObserver(function(mutations) {\n mutations.forEach(function(m) {\n m.addedNodes.forEach(function(node) {\n if (node.nodeType === 1 || node.nodeType === 3) highlight(node);\n });\n });\n });\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "Highlight Search Terms"); } } catch(__e) { console.warn('[Userscript:Highlight Search Terms]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content

Repository files navigation

webserver

A zero dependency Python 3 web server to echo back an HTTP request's headers and data.

Why?

I found myself developing a web app that sends out a webhook when a specific event occurs. I wanted a quick and painless way to set up a local server to make sure my web app was correctly sending out the webhook.

I mainly wanted to verify if it was sending the correct headers and data, so here we are.

Installation

If you're using my dotfiles, it comes pre-installed by default!

All you have to do is download the webserver script, make sure it's executable and place it somewhere on your system path.

1 liner to get webserver downloaded to /usr/local/bin:

sudo curl \
-L https://raw.githubusercontent.com/nickjj/webserver/v0.4.2/webserver \
-o /usr/local/bin/webserver && sudo chmod +x /usr/local/bin/webserver

That will download the latest release. If you want to download the bleeding edge version you can replace the version number with master to download it from the master branch.

Alternatively it's available in a Docker image:

This could be useful if you want this process to run on the same network as your other Docker containers.

docker container run -it -p 127.0.0.1:8008:8008 nickjj/webserver:v0.4.2

If you go this route, you can run the above command instead of webserver when following the docs below.

Usage

You can start the server by running webserver.

If you're not using Docker, that will listen on http://localhost:8008 by default. You can customize the bind address and port by running it with webserver 0.0.0.0:5000 or any host:port you want.

You can hit CTRL+C to stop the server.

Testing it out with curl

With your webserver running, now you can send requests to it however you see fit.

# Send a GET request with a query string.
curl localhost:8008/?just=testing
# Response (empty body):
127.0.0.1 - - [09/Sep/2020 14:23:24] "GET /?just=testing HTTP/1.1" 200 -
Host: localhost:8008
User-Agent: curl/7.68.0
Accept: */*
# Send a POST request with inline JSON data. You can use PUT, PATCH and DELETE too.
curl localhost:8008/ \
-H "Content-Type: application/json" \
-X POST --data '{"foo":"bar"}'# Response:
127.0.0.1 - - [09/Sep/2020 14:09:33] "POST / HTTP/1.1" 200 -
Host: localhost:8008
User-Agent: curl/7.68.0
Accept: */*
Content-Type: application/json
Content-Length: 13
{"foo":"bar"}
# Send a POST request with file based JSON data.echo'{"hello":"world"}'> test.json
curl localhost:8008/ \
-H "Content-Type: application/json" \
-X POST --data @test.json
# Response:
127.0.0.1 - - [09/Sep/2020 14:10:06] "POST / HTTP/1.1" 200 -
Host: localhost:8008
User-Agent: curl/7.68.0
Accept: */*
Content-Type: application/json
Content-Length: 17
{"hello":"world"}
# Send a POST request with form data.
curl localhost:8008/ \
-H "Content-Type: application/x-www-form-urlencoded" \
-X POST --data "foo=bar"# Response:
127.0.0.1 - - [09/Sep/2020 14:10:36] "POST / HTTP/1.1" 200 -
Host: localhost:8008
User-Agent: curl/7.68.0
Accept: */*
Content-Type: application/x-www-form-urlencoded
Content-Length: 7
foo=bar

If you had a Python application you could use the requests library to send requests instead of curl. Or feel free to use whatever HTTP client your programming language has available.

FAQ

What if your web app is running in Docker?

You have a few options.

Running the standalone webserver script without Docker?

You can run webserver 0.0.0.0:8008 and from within your container you can access it through host.docker.internal:8008 as long as you're using Docker Desktop.

If you're on native Linux without DD you can add this flag --add-host=host.docker.internal:host-gateway to your container's Docker command or if you're using Docker Compose you can add this property to your app's service extra_hosts: ["host.docker.internal:host-gateway"]. Now host.docker.internal will work.

Running webserver with Docker?

If everything is running in Docker Compose you can do:

services:
myapp:
# ...webserver:
image: "nickjj/webserver:v0.4.2"

From within your myapp container you'll be able to connect to webserver:8008. Basically you can access it over your container's network like usual, the same goes without using Docker Compose.

You can optionally add ports: ["127.0.0.1:8008:8008"] if you want to access the webserver locally on your Docker host with curl http://localhost:8008. In this case we're publishing the port back to your host.

What about exposing this server to the internet?

Sure. There's lots of tools you can use. One of them that's free is ngrok. No port forwarding needed!

After installing ngrok you can start your webserver and then run ngrok http 8008. A few seconds later you'll have a publicly accessible HTTPS version of this local server that you can access over the internet.

Keep in mind that's only practical for end to end tests, not a real production environment.

The above could be handy if you had a test server on the cloud that you've deployed your web app to and you wanted it to send a webhook response to your local webserver. You could configure your deployed web app to send the webhook to the ngrok address instead of localhost:8008.

Keep in mind if you're only dealing with local development you don't need to use ngrok at all.

About the Author

I'm a self taught developer and have been freelancing for the last ~20 years. You can read about everything I've learned along the way on my site at https://nickjanetakis.com. There's hundreds of blog posts and a couple of video courses on web development and deployment topics. I also have a podcast where I talk to folks about running web apps in production.

About

A zero dependency Python 3 web server to echo back an HTTP request's headers and data.

Resources

Stars

54 stars

Watchers

1 watching

Forks

Releases

Packages

Contributors

Languages

, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Strip utm_, fbclid, gclid, etc. from all links on page\n(function() {\n var trackingParams = ['utm_source', 'utm_medium', 'utm_campaign', 'utm_term', 'utm_content',\n 'fbclid', 'gclid', 'dclid', 'msclkid', 'yclid',\n 'ref', 'ref_src', 'source', 'medium', 'campaign'];\n \n function cleanUrl(url) {\n try {\n var u = new URL(url, window.location.origin);\n var changed = false;\n trackingParams.forEach(function(p) {\n if (u.searchParams.has(p)) {\n u.searchParams.delete(p);\n changed = true;\n }\n });\n return changed ? u.toString() : url;\n } catch (e) {\n return url;\n }\n }\n \n function cleanLinks() {\n document.querySelectorAll('a[href]').forEach(function(a) {\n var clean = cleanUrl(a.href);\n if (clean !== a.href) a.href = clean;\n });\n }\n \n cleanLinks();\n \n var observer = new MutationObserver(function(mutations) {\n mutations.forEach(function(m) {\n m.addedNodes.forEach(function(node) {\n if (node.nodeType === 1) {\n if (node.tagName === 'A') cleanLinks();\n node.querySelectorAll('a[href]').forEach(function(a) {\n var clean = cleanUrl(a.href);\n if (clean !== a.href) a.href = clean;\n });\n }\n });\n });\n });\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "Remove Tracking Parameters from Links"); } } catch(__e) { console.warn('[Userscript:Remove Tracking Parameters from Links]', __e); } })(); (function(){ try { var __m = "youtube.com"; var __re = new RegExp('^' + "youtube\\.com" + '
Skip to content

Repository files navigation

webserver

A zero dependency Python 3 web server to echo back an HTTP request's headers and data.

Why?

I found myself developing a web app that sends out a webhook when a specific event occurs. I wanted a quick and painless way to set up a local server to make sure my web app was correctly sending out the webhook.

I mainly wanted to verify if it was sending the correct headers and data, so here we are.

Installation

If you're using my dotfiles, it comes pre-installed by default!

All you have to do is download the webserver script, make sure it's executable and place it somewhere on your system path.

1 liner to get webserver downloaded to /usr/local/bin:

sudo curl \
-L https://raw.githubusercontent.com/nickjj/webserver/v0.4.2/webserver \
-o /usr/local/bin/webserver && sudo chmod +x /usr/local/bin/webserver

That will download the latest release. If you want to download the bleeding edge version you can replace the version number with master to download it from the master branch.

Alternatively it's available in a Docker image:

This could be useful if you want this process to run on the same network as your other Docker containers.

docker container run -it -p 127.0.0.1:8008:8008 nickjj/webserver:v0.4.2

If you go this route, you can run the above command instead of webserver when following the docs below.

Usage

You can start the server by running webserver.

If you're not using Docker, that will listen on http://localhost:8008 by default. You can customize the bind address and port by running it with webserver 0.0.0.0:5000 or any host:port you want.

You can hit CTRL+C to stop the server.

Testing it out with curl

With your webserver running, now you can send requests to it however you see fit.

# Send a GET request with a query string.
curl localhost:8008/?just=testing
# Response (empty body):
127.0.0.1 - - [09/Sep/2020 14:23:24] "GET /?just=testing HTTP/1.1" 200 -
Host: localhost:8008
User-Agent: curl/7.68.0
Accept: */*
# Send a POST request with inline JSON data. You can use PUT, PATCH and DELETE too.
curl localhost:8008/ \
-H "Content-Type: application/json" \
-X POST --data '{"foo":"bar"}'# Response:
127.0.0.1 - - [09/Sep/2020 14:09:33] "POST / HTTP/1.1" 200 -
Host: localhost:8008
User-Agent: curl/7.68.0
Accept: */*
Content-Type: application/json
Content-Length: 13
{"foo":"bar"}
# Send a POST request with file based JSON data.echo'{"hello":"world"}'> test.json
curl localhost:8008/ \
-H "Content-Type: application/json" \
-X POST --data @test.json
# Response:
127.0.0.1 - - [09/Sep/2020 14:10:06] "POST / HTTP/1.1" 200 -
Host: localhost:8008
User-Agent: curl/7.68.0
Accept: */*
Content-Type: application/json
Content-Length: 17
{"hello":"world"}
# Send a POST request with form data.
curl localhost:8008/ \
-H "Content-Type: application/x-www-form-urlencoded" \
-X POST --data "foo=bar"# Response:
127.0.0.1 - - [09/Sep/2020 14:10:36] "POST / HTTP/1.1" 200 -
Host: localhost:8008
User-Agent: curl/7.68.0
Accept: */*
Content-Type: application/x-www-form-urlencoded
Content-Length: 7
foo=bar

If you had a Python application you could use the requests library to send requests instead of curl. Or feel free to use whatever HTTP client your programming language has available.

FAQ

What if your web app is running in Docker?

You have a few options.

Running the standalone webserver script without Docker?

You can run webserver 0.0.0.0:8008 and from within your container you can access it through host.docker.internal:8008 as long as you're using Docker Desktop.

If you're on native Linux without DD you can add this flag --add-host=host.docker.internal:host-gateway to your container's Docker command or if you're using Docker Compose you can add this property to your app's service extra_hosts: ["host.docker.internal:host-gateway"]. Now host.docker.internal will work.

Running webserver with Docker?

If everything is running in Docker Compose you can do:

services:
myapp:
# ...webserver:
image: "nickjj/webserver:v0.4.2"

From within your myapp container you'll be able to connect to webserver:8008. Basically you can access it over your container's network like usual, the same goes without using Docker Compose.

You can optionally add ports: ["127.0.0.1:8008:8008"] if you want to access the webserver locally on your Docker host with curl http://localhost:8008. In this case we're publishing the port back to your host.

What about exposing this server to the internet?

Sure. There's lots of tools you can use. One of them that's free is ngrok. No port forwarding needed!

After installing ngrok you can start your webserver and then run ngrok http 8008. A few seconds later you'll have a publicly accessible HTTPS version of this local server that you can access over the internet.

Keep in mind that's only practical for end to end tests, not a real production environment.

The above could be handy if you had a test server on the cloud that you've deployed your web app to and you wanted it to send a webhook response to your local webserver. You could configure your deployed web app to send the webhook to the ngrok address instead of localhost:8008.

Keep in mind if you're only dealing with local development you don't need to use ngrok at all.

About the Author

I'm a self taught developer and have been freelancing for the last ~20 years. You can read about everything I've learned along the way on my site at https://nickjanetakis.com. There's hundreds of blog posts and a couple of video courses on web development and deployment topics. I also have a podcast where I talk to folks about running web apps in production.

About

A zero dependency Python 3 web server to echo back an HTTP request's headers and data.

Resources

Stars

54 stars

Watchers

1 watching

Forks

Releases

Packages

Contributors

Languages

, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Auto-enable theater mode on YouTube\n(function() {\n function tryTheater() {\n var btn = document.querySelector('button[aria-label=\"Theater mode\"], ytd-player #player button[title=\"Theater mode\"]');\n if (btn && !btn.classList.contains('activated')) {\n btn.click();\n }\n }\n \n // Try immediately\n tryTheater();\n \n // Try after navigation (SPA)\n var lastUrl = location.href;\n setInterval(function() {\n if (location.href !== lastUrl) {\n lastUrl = location.href;\n setTimeout(tryTheater, 500);\n }\n }, 1000);\n \n // Also try on player load\n var observer = new MutationObserver(tryTheater);\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "YouTube Theater Mode Default"); } } catch(__e) { console.warn('[Userscript:YouTube Theater Mode Default]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content

Repository files navigation

webserver

A zero dependency Python 3 web server to echo back an HTTP request's headers and data.

Why?

I found myself developing a web app that sends out a webhook when a specific event occurs. I wanted a quick and painless way to set up a local server to make sure my web app was correctly sending out the webhook.

I mainly wanted to verify if it was sending the correct headers and data, so here we are.

Installation

If you're using my dotfiles, it comes pre-installed by default!

All you have to do is download the webserver script, make sure it's executable and place it somewhere on your system path.

1 liner to get webserver downloaded to /usr/local/bin:

sudo curl \
-L https://raw.githubusercontent.com/nickjj/webserver/v0.4.2/webserver \
-o /usr/local/bin/webserver && sudo chmod +x /usr/local/bin/webserver

That will download the latest release. If you want to download the bleeding edge version you can replace the version number with master to download it from the master branch.

Alternatively it's available in a Docker image:

This could be useful if you want this process to run on the same network as your other Docker containers.

docker container run -it -p 127.0.0.1:8008:8008 nickjj/webserver:v0.4.2

If you go this route, you can run the above command instead of webserver when following the docs below.

Usage

You can start the server by running webserver.

If you're not using Docker, that will listen on http://localhost:8008 by default. You can customize the bind address and port by running it with webserver 0.0.0.0:5000 or any host:port you want.

You can hit CTRL+C to stop the server.

Testing it out with curl

With your webserver running, now you can send requests to it however you see fit.

# Send a GET request with a query string.
curl localhost:8008/?just=testing
# Response (empty body):
127.0.0.1 - - [09/Sep/2020 14:23:24] "GET /?just=testing HTTP/1.1" 200 -
Host: localhost:8008
User-Agent: curl/7.68.0
Accept: */*
# Send a POST request with inline JSON data. You can use PUT, PATCH and DELETE too.
curl localhost:8008/ \
-H "Content-Type: application/json" \
-X POST --data '{"foo":"bar"}'# Response:
127.0.0.1 - - [09/Sep/2020 14:09:33] "POST / HTTP/1.1" 200 -
Host: localhost:8008
User-Agent: curl/7.68.0
Accept: */*
Content-Type: application/json
Content-Length: 13
{"foo":"bar"}
# Send a POST request with file based JSON data.echo'{"hello":"world"}'> test.json
curl localhost:8008/ \
-H "Content-Type: application/json" \
-X POST --data @test.json
# Response:
127.0.0.1 - - [09/Sep/2020 14:10:06] "POST / HTTP/1.1" 200 -
Host: localhost:8008
User-Agent: curl/7.68.0
Accept: */*
Content-Type: application/json
Content-Length: 17
{"hello":"world"}
# Send a POST request with form data.
curl localhost:8008/ \
-H "Content-Type: application/x-www-form-urlencoded" \
-X POST --data "foo=bar"# Response:
127.0.0.1 - - [09/Sep/2020 14:10:36] "POST / HTTP/1.1" 200 -
Host: localhost:8008
User-Agent: curl/7.68.0
Accept: */*
Content-Type: application/x-www-form-urlencoded
Content-Length: 7
foo=bar

If you had a Python application you could use the requests library to send requests instead of curl. Or feel free to use whatever HTTP client your programming language has available.

FAQ

What if your web app is running in Docker?

You have a few options.

Running the standalone webserver script without Docker?

You can run webserver 0.0.0.0:8008 and from within your container you can access it through host.docker.internal:8008 as long as you're using Docker Desktop.

If you're on native Linux without DD you can add this flag --add-host=host.docker.internal:host-gateway to your container's Docker command or if you're using Docker Compose you can add this property to your app's service extra_hosts: ["host.docker.internal:host-gateway"]. Now host.docker.internal will work.

Running webserver with Docker?

If everything is running in Docker Compose you can do:

services:
myapp:
# ...webserver:
image: "nickjj/webserver:v0.4.2"

From within your myapp container you'll be able to connect to webserver:8008. Basically you can access it over your container's network like usual, the same goes without using Docker Compose.

You can optionally add ports: ["127.0.0.1:8008:8008"] if you want to access the webserver locally on your Docker host with curl http://localhost:8008. In this case we're publishing the port back to your host.

What about exposing this server to the internet?

Sure. There's lots of tools you can use. One of them that's free is ngrok. No port forwarding needed!

After installing ngrok you can start your webserver and then run ngrok http 8008. A few seconds later you'll have a publicly accessible HTTPS version of this local server that you can access over the internet.

Keep in mind that's only practical for end to end tests, not a real production environment.

The above could be handy if you had a test server on the cloud that you've deployed your web app to and you wanted it to send a webhook response to your local webserver. You could configure your deployed web app to send the webhook to the ngrok address instead of localhost:8008.

Keep in mind if you're only dealing with local development you don't need to use ngrok at all.

About the Author

I'm a self taught developer and have been freelancing for the last ~20 years. You can read about everything I've learned along the way on my site at https://nickjanetakis.com. There's hundreds of blog posts and a couple of video courses on web development and deployment topics. I also have a podcast where I talk to folks about running web apps in production.

About

A zero dependency Python 3 web server to echo back an HTTP request's headers and data.

Resources

Stars

54 stars

Watchers

1 watching

Forks

Releases

Packages

Contributors

Languages

, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Remove or un-stick sticky/fixed headers that block content\n(function() {\n function unstick() {\n document.querySelectorAll('header, nav, [role=\"banner\"], .header, .navbar, .sticky, .fixed-top, [style*=\"position: fixed\"], [style*=\"position:sticky\"]').forEach(function(el) {\n if (el.style.position === 'fixed' || el.style.position === 'sticky' || \n getComputedStyle(el).position === 'fixed' || getComputedStyle(el).position === 'sticky') {\n el.style.position = 'static';\n el.style.top = 'auto';\n el.style.zIndex = 'auto';\n }\n });\n }\n \n unstick();\n \n var observer = new MutationObserver(unstick);\n observer.observe(document.body, { childList: true, subtree: true, attributes: true, attributeFilter: ['style', 'class'] });\n})();", "Kill Sticky Headers"); } } catch(__e) { console.warn('[Userscript:Kill Sticky Headers]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content

Repository files navigation

webserver

A zero dependency Python 3 web server to echo back an HTTP request's headers and data.

Why?

I found myself developing a web app that sends out a webhook when a specific event occurs. I wanted a quick and painless way to set up a local server to make sure my web app was correctly sending out the webhook.

I mainly wanted to verify if it was sending the correct headers and data, so here we are.

Installation

If you're using my dotfiles, it comes pre-installed by default!

All you have to do is download the webserver script, make sure it's executable and place it somewhere on your system path.

1 liner to get webserver downloaded to /usr/local/bin:

sudo curl \
-L https://raw.githubusercontent.com/nickjj/webserver/v0.4.2/webserver \
-o /usr/local/bin/webserver && sudo chmod +x /usr/local/bin/webserver

That will download the latest release. If you want to download the bleeding edge version you can replace the version number with master to download it from the master branch.

Alternatively it's available in a Docker image:

This could be useful if you want this process to run on the same network as your other Docker containers.

docker container run -it -p 127.0.0.1:8008:8008 nickjj/webserver:v0.4.2

If you go this route, you can run the above command instead of webserver when following the docs below.

Usage

You can start the server by running webserver.

If you're not using Docker, that will listen on http://localhost:8008 by default. You can customize the bind address and port by running it with webserver 0.0.0.0:5000 or any host:port you want.

You can hit CTRL+C to stop the server.

Testing it out with curl

With your webserver running, now you can send requests to it however you see fit.

# Send a GET request with a query string.
curl localhost:8008/?just=testing
# Response (empty body):
127.0.0.1 - - [09/Sep/2020 14:23:24] "GET /?just=testing HTTP/1.1" 200 -
Host: localhost:8008
User-Agent: curl/7.68.0
Accept: */*
# Send a POST request with inline JSON data. You can use PUT, PATCH and DELETE too.
curl localhost:8008/ \
-H "Content-Type: application/json" \
-X POST --data '{"foo":"bar"}'# Response:
127.0.0.1 - - [09/Sep/2020 14:09:33] "POST / HTTP/1.1" 200 -
Host: localhost:8008
User-Agent: curl/7.68.0
Accept: */*
Content-Type: application/json
Content-Length: 13
{"foo":"bar"}
# Send a POST request with file based JSON data.echo'{"hello":"world"}'> test.json
curl localhost:8008/ \
-H "Content-Type: application/json" \
-X POST --data @test.json
# Response:
127.0.0.1 - - [09/Sep/2020 14:10:06] "POST / HTTP/1.1" 200 -
Host: localhost:8008
User-Agent: curl/7.68.0
Accept: */*
Content-Type: application/json
Content-Length: 17
{"hello":"world"}
# Send a POST request with form data.
curl localhost:8008/ \
-H "Content-Type: application/x-www-form-urlencoded" \
-X POST --data "foo=bar"# Response:
127.0.0.1 - - [09/Sep/2020 14:10:36] "POST / HTTP/1.1" 200 -
Host: localhost:8008
User-Agent: curl/7.68.0
Accept: */*
Content-Type: application/x-www-form-urlencoded
Content-Length: 7
foo=bar

If you had a Python application you could use the requests library to send requests instead of curl. Or feel free to use whatever HTTP client your programming language has available.

FAQ

What if your web app is running in Docker?

You have a few options.

Running the standalone webserver script without Docker?

You can run webserver 0.0.0.0:8008 and from within your container you can access it through host.docker.internal:8008 as long as you're using Docker Desktop.

If you're on native Linux without DD you can add this flag --add-host=host.docker.internal:host-gateway to your container's Docker command or if you're using Docker Compose you can add this property to your app's service extra_hosts: ["host.docker.internal:host-gateway"]. Now host.docker.internal will work.

Running webserver with Docker?

If everything is running in Docker Compose you can do:

services:
myapp:
# ...webserver:
image: "nickjj/webserver:v0.4.2"

From within your myapp container you'll be able to connect to webserver:8008. Basically you can access it over your container's network like usual, the same goes without using Docker Compose.

You can optionally add ports: ["127.0.0.1:8008:8008"] if you want to access the webserver locally on your Docker host with curl http://localhost:8008. In this case we're publishing the port back to your host.

What about exposing this server to the internet?

Sure. There's lots of tools you can use. One of them that's free is ngrok. No port forwarding needed!

After installing ngrok you can start your webserver and then run ngrok http 8008. A few seconds later you'll have a publicly accessible HTTPS version of this local server that you can access over the internet.

Keep in mind that's only practical for end to end tests, not a real production environment.

The above could be handy if you had a test server on the cloud that you've deployed your web app to and you wanted it to send a webhook response to your local webserver. You could configure your deployed web app to send the webhook to the ngrok address instead of localhost:8008.

Keep in mind if you're only dealing with local development you don't need to use ngrok at all.

About the Author

I'm a self taught developer and have been freelancing for the last ~20 years. You can read about everything I've learned along the way on my site at https://nickjanetakis.com. There's hundreds of blog posts and a couple of video courses on web development and deployment topics. I also have a podcast where I talk to folks about running web apps in production.

About

A zero dependency Python 3 web server to echo back an HTTP request's headers and data.

Resources

Stars

54 stars

Watchers

1 watching

Forks

Releases

Packages

Contributors

Languages

, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Universal Dark Mode - works on any site\n(function() {\n var enabled = true;\n \n function applyDarkMode() {\n if (!enabled) return;\n \n // Create style element if it doesn't exist\n var style = document.getElementById('universal-dark-mode-style');\n if (!style) {\n style = document.createElement('style');\n style.id = 'universal-dark-mode-style';\n document.head.appendChild(style);\n }\n \n // Dark mode CSS - inverts colors but preserves images/video\n style.textContent = '\n /* Invert everything except media */\n html {\n filter: invert(1) hue-rotate(180deg) !important;\n background: #1a1a2e !important;\n }\n \n /* Restore images, videos, iframes, canvas */\n img, video, iframe, canvas, svg, picture, [style*=\"background-image\"] {\n filter: invert(1) hue-rotate(180deg) !important;\n }\n \n /* Preserve specific elements that should not be inverted */\n .no-dark-mode, .no-dark-mode *,\n [data-theme=\"light\"], [data-theme=\"light\"],\n .ace_editor, .ace_editor *,\n .CodeMirror, .CodeMirror *,\n .monaco-editor, .monaco-editor *,\n .markdown-body pre, .markdown-body pre *,\n .highlight, .highlight *,\n pre code, pre code * {\n filter: none !important;\n }\n \n /* Fix common UI elements */\n .modal, .popup, .dropdown-menu, .tooltip, .popover {\n filter: invert(1) hue-rotate(180deg) !important;\n background: #2d2d44 !important;\n border-color: #444 !important;\n }\n \n /* Scrollbars */\n ::-webkit-scrollbar { background: #1a1a2e !important; }\n ::-webkit-scrollbar-thumb { background: #444 !important; }\n ::-webkit-scrollbar-thumb:hover { background: #555 !important; }\n \n /* Selection */\n ::selection { background: #4ecdc4 !important; color: #1a1a2e !important; }\n ::-moz-selection { background: #4ecdc4 !important; color: #1a1a2e !important; }\n ';\n }\n \n function removeDarkMode() {\n var style = document.getElementById('universal-dark-mode-style');\n if (style) style.remove();\n }\n \n // Toggle with Alt+Shift+D\n document.addEventListener('keydown', function(e) {\n if (e.altKey && e.shiftKey && e.key === 'D') {\n e.preventDefault();\n enabled = !enabled;\n if (enabled) {\n applyDarkMode();\n console.log('[Universal Dark Mode] Enabled');\n } else {\n removeDarkMode();\n console.log('[Universal Dark Mode] Disabled');\n }\n }\n });\n \n // Apply on load\n applyDarkMode();\n \n // Re-apply on dynamic content\n var observer = new MutationObserver(function(mutations) {\n if (enabled && !document.getElementById('universal-dark-mode-style')) {\n applyDarkMode();\n }\n });\n observer.observe(document.head, { childList: true });\n \n console.log('[Universal Dark Mode] Loaded - Press Alt+Shift+D to toggle');\n})();", "Universal Dark Mode"); } } catch(__e) { console.warn('[Userscript:Universal Dark Mode]', __e); } })(); })();
Skip to content

Repository files navigation

webserver

A zero dependency Python 3 web server to echo back an HTTP request's headers and data.

Why?

I found myself developing a web app that sends out a webhook when a specific event occurs. I wanted a quick and painless way to set up a local server to make sure my web app was correctly sending out the webhook.

I mainly wanted to verify if it was sending the correct headers and data, so here we are.

Installation

If you're using my dotfiles, it comes pre-installed by default!

All you have to do is download the webserver script, make sure it's executable and place it somewhere on your system path.

1 liner to get webserver downloaded to /usr/local/bin:

sudo curl \
-L https://raw.githubusercontent.com/nickjj/webserver/v0.4.2/webserver \
-o /usr/local/bin/webserver && sudo chmod +x /usr/local/bin/webserver

That will download the latest release. If you want to download the bleeding edge version you can replace the version number with master to download it from the master branch.

Alternatively it's available in a Docker image:

This could be useful if you want this process to run on the same network as your other Docker containers.

docker container run -it -p 127.0.0.1:8008:8008 nickjj/webserver:v0.4.2

If you go this route, you can run the above command instead of webserver when following the docs below.

Usage

You can start the server by running webserver.

If you're not using Docker, that will listen on http://localhost:8008 by default. You can customize the bind address and port by running it with webserver 0.0.0.0:5000 or any host:port you want.

You can hit CTRL+C to stop the server.

Testing it out with curl

With your webserver running, now you can send requests to it however you see fit.

# Send a GET request with a query string.
curl localhost:8008/?just=testing
# Response (empty body):
127.0.0.1 - - [09/Sep/2020 14:23:24] "GET /?just=testing HTTP/1.1" 200 -
Host: localhost:8008
User-Agent: curl/7.68.0
Accept: */*
# Send a POST request with inline JSON data. You can use PUT, PATCH and DELETE too.
curl localhost:8008/ \
-H "Content-Type: application/json" \
-X POST --data '{"foo":"bar"}'# Response:
127.0.0.1 - - [09/Sep/2020 14:09:33] "POST / HTTP/1.1" 200 -
Host: localhost:8008
User-Agent: curl/7.68.0
Accept: */*
Content-Type: application/json
Content-Length: 13
{"foo":"bar"}
# Send a POST request with file based JSON data.echo'{"hello":"world"}'> test.json
curl localhost:8008/ \
-H "Content-Type: application/json" \
-X POST --data @test.json
# Response:
127.0.0.1 - - [09/Sep/2020 14:10:06] "POST / HTTP/1.1" 200 -
Host: localhost:8008
User-Agent: curl/7.68.0
Accept: */*
Content-Type: application/json
Content-Length: 17
{"hello":"world"}
# Send a POST request with form data.
curl localhost:8008/ \
-H "Content-Type: application/x-www-form-urlencoded" \
-X POST --data "foo=bar"# Response:
127.0.0.1 - - [09/Sep/2020 14:10:36] "POST / HTTP/1.1" 200 -
Host: localhost:8008
User-Agent: curl/7.68.0
Accept: */*
Content-Type: application/x-www-form-urlencoded
Content-Length: 7
foo=bar

If you had a Python application you could use the requests library to send requests instead of curl. Or feel free to use whatever HTTP client your programming language has available.

FAQ

What if your web app is running in Docker?

You have a few options.

Running the standalone webserver script without Docker?

You can run webserver 0.0.0.0:8008 and from within your container you can access it through host.docker.internal:8008 as long as you're using Docker Desktop.

If you're on native Linux without DD you can add this flag --add-host=host.docker.internal:host-gateway to your container's Docker command or if you're using Docker Compose you can add this property to your app's service extra_hosts: ["host.docker.internal:host-gateway"]. Now host.docker.internal will work.

Running webserver with Docker?

If everything is running in Docker Compose you can do:

services:
myapp:
# ...webserver:
image: "nickjj/webserver:v0.4.2"

From within your myapp container you'll be able to connect to webserver:8008. Basically you can access it over your container's network like usual, the same goes without using Docker Compose.

You can optionally add ports: ["127.0.0.1:8008:8008"] if you want to access the webserver locally on your Docker host with curl http://localhost:8008. In this case we're publishing the port back to your host.

What about exposing this server to the internet?

Sure. There's lots of tools you can use. One of them that's free is ngrok. No port forwarding needed!

After installing ngrok you can start your webserver and then run ngrok http 8008. A few seconds later you'll have a publicly accessible HTTPS version of this local server that you can access over the internet.

Keep in mind that's only practical for end to end tests, not a real production environment.

The above could be handy if you had a test server on the cloud that you've deployed your web app to and you wanted it to send a webhook response to your local webserver. You could configure your deployed web app to send the webhook to the ngrok address instead of localhost:8008.

Keep in mind if you're only dealing with local development you don't need to use ngrok at all.

About the Author

I'm a self taught developer and have been freelancing for the last ~20 years. You can read about everything I've learned along the way on my site at https://nickjanetakis.com. There's hundreds of blog posts and a couple of video courses on web development and deployment topics. I also have a podcast where I talk to folks about running web apps in production.

About

A zero dependency Python 3 web server to echo back an HTTP request's headers and data.

Resources

Stars

54 stars

Watchers

1 watching

Forks

Releases

Packages

Contributors

Languages