68
\$\begingroup\$

As we all should know, there's a HTTP status code 418: I'm a teapot.

Your mission, should you choose to accept it, is to use your creativitea and write the smallest possible server that responds with the above status code to any and every HTTP request made to it.

Standard loopholes apply, including

Fetching the desired output from an external source

This includes doing an HTTP request to fetch the page with the question and extracting a solution from that page. This was mildly amusing back in 2011, but now is derivative and uninteresting.

Meaning you cannot simply redirect the request to another server to have it return the response.


Addressing some confusion about server functionality:
Your server can do anything (or nothing) while no HTTP request is made to it as long as it replies with the correct response once a HTTP request is made.

\$\endgroup\$
  • 15
    \$\begingroup\$ to each and every http request? Surely just ones to a coffee: URI? \$\endgroup\$ – dave Nov 19 '14 at 18:24
  • 3
    \$\begingroup\$ May we assume we already have root privileges? (e.g. bind() to port 80 is ok) \$\endgroup\$ – Digital Trauma Nov 19 '14 at 20:03
  • 2
    \$\begingroup\$ @DigitalTrauma Yes, you can assume escalated privileges for your server. \$\endgroup\$ – Nit Nov 19 '14 at 23:26
  • 4
    \$\begingroup\$ @Knerd I'm leaning on the no side, you're not writing a program, you're simply configuring one. \$\endgroup\$ – Nit Nov 20 '14 at 17:10
  • 2
    \$\begingroup\$ omg. With the IOT coming around, this status code may have an actual reason to exist! \$\endgroup\$ – Luminous Nov 20 '14 at 18:48

27 Answers 27

39
\$\begingroup\$

GNU Awk: 69 characters

A server itself (endlessly serves one request at a time), no library used.

Send 418 to everybody who connects (82 69 characters):

BEGIN{while(s="/inet/tcp/80/0/0"){print"HTTP/1.1 418\n"|&s
close(s)}}

Send 418 to everybody who sends something (93 80 characters):

BEGIN{while(s="/inet/tcp/80/0/0"){s|&getline
print"HTTP/1.1 418\n"|&s
close(s)}}

Send 418 to everybody who sends a valid HTTP GET request (122 109 characters):

BEGIN{while(s="/inet/tcp/80/0/0"){s|&getline
if(/^GET \S+ HTTP\/1\.[01]$/)print"HTTP/1.1 418\n"|&s
close(s)}}
\$\endgroup\$
  • \$\begingroup\$ But .. how to connect ? ;) \$\endgroup\$ – Optimizer Nov 19 '14 at 13:31
  • 5
    \$\begingroup\$ The same way you connect to any web server. Browser, netcat, telnet, wget, curl, another GNU awk script, … Theoretically it listens on localhost:80, but for that 1) no web server, Skype or other program should use port 80; 2) you have to be super user to open ports below 1024. So for testing is easier to edit the port number in the script to something like 8080 (s="/inet/tcp/8080/0/0") then connect to that. pastebin.com/zauP7LMA \$\endgroup\$ – manatwork Nov 19 '14 at 13:43
  • 2
    \$\begingroup\$ I see. Cool. Awk noob here :) \$\endgroup\$ – Optimizer Nov 19 '14 at 14:10
  • 1
    \$\begingroup\$ You could possibly save a byte by using smaller port like 8, which is unassigned. \$\endgroup\$ – Hannes Karppila Mar 20 '16 at 9:01
  • \$\begingroup\$ @HannesKarppila, that's correct. But given that all other solutions which explicitly specify a port (excepting the Haskell answer's port 8888) uses port 80, I better keep it like this for comparability. \$\endgroup\$ – manatwork Mar 21 '16 at 8:30
32
\$\begingroup\$

Bash (33)

nc -lp80 -q1<<<"HTTP/1.1 418
";$0
\$\endgroup\$
  • 3
    \$\begingroup\$ Are the two newlines necessary? Seems to work OK with only one for me. Also by my count the above is 34 bytes - I'm guessing your editor is adding an unnecessary newline or \0 to the end of your file - you can truncate this and it still works. s='echo HTTP/1.1 418|nc -lp80 -q1;$0' ; echo ${#s} gives 33 for me \$\endgroup\$ – Digital Trauma Nov 20 '14 at 0:56
  • \$\begingroup\$ @DigitalTrauma: You are right - the final newline is added automatically in here strings: Why does a bash here-string add a trailing newline char? ------ But I see two possible problems: 1. The script expects that it is stored in one of the $PATH directories or that it is called with a path (recursion by $0). ----- 2. HTTP requires that lines are terminated by \r\n not only \n. Here string should be $"HTTP/1.1 418\r\n\r" (longer readable form). ------ And finally: The script could be shorter: The -q1 parameter is not necessary. \$\endgroup\$ – pabouk Nov 20 '14 at 9:02
  • 2
    \$\begingroup\$ @DigitalTrauma, @pabouk: The output needs end with two newlines. So one of the newlines was unnecessary (because of the here-string), but the echo variant does not work (at least Firefox won't recognize it as a 418). However, the \rs aren't needed. The spec says it should be \r\n\r\n, but at least Firefox and Chrome will accept \n\n, so it seems to be in the spirit of golfing not to include them. The -q1 parameter was necessary on my system, because the browser will not close the connection by itself. $0 works fine if the script is made executable and called in that manner. \$\endgroup\$ – marinus Nov 20 '14 at 15:28
  • \$\begingroup\$ @marinus Interesting - I was testing with wget which seems to be fine with just one newline \$\endgroup\$ – Digital Trauma Nov 20 '14 at 16:06
  • 1
    \$\begingroup\$ @pabouk - Interesting snippet here w3.org/Protocols/HTTP/OldServers.html: "Lines should be regarded as terminated by the Line Feed, and the preceeding Carriage Return character ignored" \$\endgroup\$ – Digital Trauma Nov 20 '14 at 16:09
30
\$\begingroup\$

PHP - 85 bytes

<?for($s=socket_create_listen(80);socket_write(socket_accept($s),"HTTP/1.1 418
"););

Saved with Windows-Style (CR-LF) line endings, requires php_sockets enabled.

I actually used this as my error code for the Hard Code Golf: Create a Chatroom challenge, but no one noticed.


Browser-Friendly version

<?for(socket_getsockname($s=socket_create_listen(80),$n);$t="I'm a teapot";socket_write($c=socket_accept($s),"HTTP/1.0 418 $t
Content-Length: $l

<title>418 $t</title><h1>$t</h1>The requested resource is not suitable for brewing coffee.<hr><i>$n:80</i>"))$l=124+strlen($n);

Start the script in the CLI, and point your browser at http://localhost.

\$\endgroup\$
  • 1
    \$\begingroup\$ +1 for user firendlyness / I'm a teapot :-) \$\endgroup\$ – Levite Feb 25 '15 at 7:28
20
\$\begingroup\$

Node.js (LiveScript)

http module - 66

require(\http)createServer (->&1.writeHead 418;&1.end!) .listen 80

Inspired by Qwertiy's answer.

net module - 76

require(\net)createServer (->it.write 'HTTP/1.1 418\r\n';it.end!) .listen 80
\$\endgroup\$
  • 2
    \$\begingroup\$ Could the person who downvoted care to explain why? \$\endgroup\$ – nyuszika7h Nov 30 '14 at 17:40
20
\$\begingroup\$

Ruby + Rack, 19 bytes

run->e{[418,{},[]]}

Must be saved as config.ru, and run with the rackup command.

Or if you prefer "pure" Ruby:

Rack::Handler::WEBrick.run->e{[418,{},[]]}

42 bytes + -rrack flag = 48 bytes

\$\endgroup\$
12
\$\begingroup\$

Bash+BSD general commands, 29

Borrowing back a little bit from other answers:

nc -lp80<<<"HTTP/1.1 418
";$0

Works for me with wget.

First answer to use nc, 38

for((;;)){
nc -l 80 <<<HTTP/1.1\ 418
}

I'm assuming root privileges - run as follows:

sudo bash ./418.sh
\$\endgroup\$
  • 3
    \$\begingroup\$ @ub3rst4r Correct - That is why I stated "BSD general commands", which may be considered as a "library" from the point of view of shell scripting. From the OP: "All libraries are welcome" \$\endgroup\$ – Digital Trauma Nov 20 '14 at 0:37
  • 2
    \$\begingroup\$ A response must end with a newline, see w3.org/Protocols/HTTP/Response.html \$\endgroup\$ – Nit Nov 20 '14 at 6:57
  • 2
    \$\begingroup\$ @Nit - Yes - bash "here strings" will automatically be appended with a newline \$\endgroup\$ – Digital Trauma Nov 20 '14 at 16:03
  • 1
    \$\begingroup\$ How about nc -l 80 <<<HTTP/1.1\ 418;$0 \$\endgroup\$ – core1024 Nov 20 '14 at 16:46
  • 1
    \$\begingroup\$ Sorry for the confusion with the two spaces. I did not notice that you did not use the -p switch :) I tested the code with Firefox and without two newlines the status code is not recognized. \$\endgroup\$ – pabouk Nov 20 '14 at 20:21
9
\$\begingroup\$

Ruby (nc system command) - 35

loop{`nc -l 80 <<<"HTTP/1.1 418"`}

DigitalTrauma should get the credit for the idea of using nc, however Ruby can make an infinite loop with fewer characters than Bash :)

Ruby (TCPServer) - 75

require'socket'
s=TCPServer.new 80
loop{(s.accept<<'HTTP/1.1 418
').close}

That newline is intentional -- the actual newline character is one character shorter than "\n".

Ruby (WEBrick HTTPServer) - 87

require'webrick'
(s=WEBrick::HTTPServer.new).mount_proc(?/){|_,r|r.status=418}
s.start
\$\endgroup\$
  • \$\begingroup\$ A response must end with a newline, see w3.org/Protocols/HTTP/Response.html \$\endgroup\$ – Nit Nov 20 '14 at 6:56
  • 1
    \$\begingroup\$ @DigitalTrauma, I was going to use that, but then realized the backslash needs to be escaped with another backslash, so it would have been the same number of characters anyway :) \$\endgroup\$ – Trey Thomas Nov 20 '14 at 17:17
  • \$\begingroup\$ @TreyThomas Oh I see - so Ruby needs an extra level of escape here \$\endgroup\$ – Digital Trauma Nov 20 '14 at 17:23
8
\$\begingroup\$

Node.js, 80

require('http').createServer(function(q,s){s.writeHead(418);s.end()}).listen(80)

The response is

HTTP/1.1 418 I'm a teapot
Date: Wed, 19 Nov 2014 21:08:27 GMT
Connection: keep-alive
Transfer-Encoding: chunked

0
\$\endgroup\$
  • 2
    \$\begingroup\$ I find it just awesome that node supports that error code natively ^^ \$\endgroup\$ – Levite Feb 25 '15 at 7:31
8
\$\begingroup\$

Python 3 106

s=__import__('socket').socket(2,1) 
s.bind(('',80))
s.listen(9)
while 1:s.accept()[0].send('HTTP/1.1 418\n')
\$\endgroup\$
  • 1
    \$\begingroup\$ Based on hallvabo's comment in Tips for golfing in Python, from socket import*;s=socket(AF_INET,SOCK_STREAM) is shorter. \$\endgroup\$ – manatwork Nov 19 '14 at 19:30
  • \$\begingroup\$ @manatwork Thanks, is there a shorter way to infinite loop? I didn't find one in the tips... \$\endgroup\$ – Tuomas Laakkonen Nov 19 '14 at 19:33
  • 3
    \$\begingroup\$ while 1:s.accept()[0].sendall(bytes('HTTP/1.1 418\n','UTF8')) – unless I missed something. (By the way, feel free to count newlines a single characters, as the language allows them. That way you loose nothing by separating the commands by newlines instead of ;.) \$\endgroup\$ – manatwork Nov 19 '14 at 19:39
  • \$\begingroup\$ You can cut off 2 characters by assuming port 80 is accessible, according to the question owner's comment. One ugly thing which may break portability, but may be acceptable here: use the constants' values directly s=socket(2,1) (at least those are their values on my Linux). \$\endgroup\$ – manatwork Nov 20 '14 at 11:46
  • \$\begingroup\$ The documentation says for listen()'s parameter that “the maximum value is system-dependent (usually 5)”. So instead of 10, 9 is more that enough and 1 character shorter. And instead of bytes('HTTP/1.1 418\n','UTF8') a literal b'HTTP/1.1 418\n' is enough. Or if you make the code Python 2, then the b bytesprefix is not needed anymore. And the shorter send() also seems to be enough. \$\endgroup\$ – manatwork Nov 20 '14 at 17:32
7
\$\begingroup\$

Haskell - 142 bytes

import Network
import System.IO
main=listenOn(PortNumber 8888)>>=f
f s=do{(h,_,_)<-accept s;hPutStr h"HTTP/1.1 418\r\n";hFlush h;hClose h;f s}
\$\endgroup\$
5
\$\begingroup\$

Tcl (>= 8.5), 78 bytes

Edit - added in an extra newline (total of 2 newlines) for the sake of compliance.

socket -server {apply {{c - -} {puts $c "HTTP/1.1 418
";close $c}}} 80
vwait f
\$\endgroup\$
  • \$\begingroup\$ A response must end with a newline, see w3.org/Protocols/HTTP/Response.html \$\endgroup\$ – Nit Nov 20 '14 at 6:58
  • 3
    \$\begingroup\$ @Nit - Yes, Tcl puts will automatically append a newline, unless the -nonewline option is given. tcl.tk/man/tcl/TclCmd/puts.htm \$\endgroup\$ – Digital Trauma Nov 20 '14 at 16:05
5
\$\begingroup\$

Julia: 86 73 characters

s=listen(80)
while 1<2
c=accept(s)
write(c,"HTTP/1.1 418

")
close(c)
end
\$\endgroup\$
  • \$\begingroup\$ I don't think you need the actual "I'm a teapot" part -- the response code should be enough. \$\endgroup\$ – Desty Nov 21 '14 at 10:22
  • \$\begingroup\$ Yes, I noticed it. But as that won't help much on Julia's score I kept it complete. But probably would be better to remove it to facilitate comparison of languages. \$\endgroup\$ – manatwork Nov 21 '14 at 11:08
5
\$\begingroup\$

Powershell, 398

$Listener = New-Object System.Net.Sockets.TcpListener([System.Net.IPAddress]::Parse("10.10.10.10"), 80)
$Listener.Start()
while($true)
{
    $RemoteClient = $Listener.AcceptTcpClient()
    $Stream = $RemoteClient.GetStream()
    $Writer = New-Object System.IO.StreamWriter $Stream
    $Writer.Write("HTTP/1.1 418 I'm a Teapot`nConnection: Close`n`n")
    $Writer.Flush()
    $RemoteClient.Close()
}

258

$l=New-Object System.Net.Sockets.TcpListener([System.Net.IPAddress]::Parse("10.10.10.10"),80);$l.Start();while($true){$r = $l.AcceptTcpClient();$s = $r.GetStream();$w = New-Object System.IO.StreamWriter $s;$w.Write("HTTP/1.1 418`n`n");$w.Flush();$r.Close()}
\$\endgroup\$
5
\$\begingroup\$

R, 80 characters

Never did socket programming with R before, but I'll give it a try:

repeat{s=socketConnection(,80,T,open="r+");cat("HTTP/1.1 418\n",file=s);close(s)}

Here socketConnection opens a socket: first argument should be the host, the default being localhost we can skip it here; the second argument is the port which has no default, then argument server when specified TRUE creates the socket, if FALSE it just connects to an existing one. T is, by default, equals to TRUE, in R.

Edit: As suggested in a suggested edit by @AlexBrown, this could be shorten into 69 characters:

repeat cat("HTTP/1.1 418\n",file=s<-socketConnection(,80,T))+close(s)
\$\endgroup\$
4
\$\begingroup\$

Node.js koa, 61 Bytes

require('koa')().use(function*(){this.status=418}).listen(80)

Response:

HTTP/1.1 418 I'm a teapot
X-Powered-By: koa
Content-Type: text/plain; charset=utf-8
Content-Length: 12
Date: Thu, 20 Nov 2014 07:20:36 GMT
Connection: close

I'm a teapot

Requires node v0.11.12 +

Run as:

node --harmony app.js
\$\endgroup\$
  • \$\begingroup\$ What's function*? \$\endgroup\$ – nyuszika7h Nov 30 '14 at 17:53
  • 2
    \$\begingroup\$ That's a generator function, part of the ECMAScript 6, Harmony proposal. \$\endgroup\$ – c.P.u1 Dec 1 '14 at 5:56
4
\$\begingroup\$

Shell + socat, 60

socat tcp-l:80,fork exec:'printf HTTP/1.1\\ 418\\ T\r\n\r\n'
\$\endgroup\$
  • \$\begingroup\$ echo -e HTTP/1.1 418 T\r\n\r is shorter. \$\endgroup\$ – jimmy23013 Nov 20 '14 at 15:02
  • \$\begingroup\$ The \\ T isn't even needed. \$\endgroup\$ – nyuszika7h Nov 30 '14 at 17:51
3
\$\begingroup\$

MATLAB, 97 86 bytes

Not really a serious contender in terms of absolute byte-count, but I'd like to post it because I didn't think it would be possible to write a fully functional webserver using a mathematical tool. Note the use of property shortening: 'Ne','s' internally expands to 'NetworkRole', 'server'.

t=tcpip('0.0.0.0','Ne','s');while 1
fopen(t)
fprintf(t,'HTTP/1.1 418\n')
fclose(t)
end
\$\endgroup\$
3
\$\begingroup\$

You can do this with minimal effort using a .htaccess file and php.

All the accesses to your server will return the status 418.

Below is the code:

.htaccess (28 bytes)

RewriteRule .* index.php [L]

PHP (38 19 bytes)

<<?header(TE,1,418);

Thanks to @primo for saving me a bunch of bytes!


I have tested this and confirm it returns the desired result!

http://i.stack.imgur.com/wLb9p.png

By the way, "Pedido" means "Request" and "Resposta" means "Answer".

\$\endgroup\$
  • \$\begingroup\$ -1, this is not a complete program. It relies on an external web server. \$\endgroup\$ – nyuszika7h Nov 30 '14 at 17:54
  • \$\begingroup\$ @nyuszika7h Actually, it relies on Apache with PHP installed as a module. Your argument is both valid and invalid. Apache only redirects the accesses to the PHP file, the PHP file takes care of the code. \$\endgroup\$ – Ismael Miguel Nov 30 '14 at 17:55
  • \$\begingroup\$ @nyuszika7h If we go down on that layer, then you can't even use the console to run your PHP code. Apache is the starter. The trigger that fires the bullet. Running the PHP file from the console, would make the console the trigger. \$\endgroup\$ – Ismael Miguel Nov 30 '14 at 18:01
  • \$\begingroup\$ You're relying on having Apache already running, and I don't think it will work without changing the default configuration either. I don't care what you say, there's no way I can see this as being valid. But you should ask @Nit, as it's their question. \$\endgroup\$ – nyuszika7h Nov 30 '14 at 18:02
  • \$\begingroup\$ @nyuszika7h If it was invalid, the OP would have said already. \$\endgroup\$ – Ismael Miguel Nov 30 '14 at 18:05
2
\$\begingroup\$

node.js with CoffeeScript (76)

require("connect")().use((q,s,n)->s.writeHead 418;s.end();return;).listen 80

Just compile it to JavaScript, then you need to run npm install connect. After that start it with node server.js

\$\endgroup\$
2
\$\begingroup\$

nginx - 35

events{}http{server{return 418;}}

Throw that in nginx.conf, start nginx.

Not sure if this uses standard loopholes "Using built-in functions to do the work" or "Interpreting the challenge too literally." Oops, looks like OP won't like this answer.

\$\endgroup\$
  • \$\begingroup\$ Would it still work if you dropped the ;? \$\endgroup\$ – Cyril Nov 23 '14 at 8:58
  • \$\begingroup\$ +4/-4: well done on controversy :D \$\endgroup\$ – cat Mar 20 '16 at 2:45
2
\$\begingroup\$

Perl, 78

use Web::Simple;sub dispatch_request{sub{[418,[],[]]}}__PACKAGE__->to_psgi_app

run as plackup whatever.pl.

\$\endgroup\$
  • \$\begingroup\$ If you want a plack application, then just sub{[418,[],[]]} should be sufficient. (16 characters.) \$\endgroup\$ – tobyink Nov 24 '14 at 3:57
  • \$\begingroup\$ Of course you're right! It's not like I'm using any of the framework, why load it? :) \$\endgroup\$ – hobbs Nov 24 '14 at 4:55
  • \$\begingroup\$ @tobyink feel free to submit it as your own though :) \$\endgroup\$ – hobbs Nov 24 '14 at 4:56
2
\$\begingroup\$

Python 2.7/Django, 94 bytes

(added from default boilerplate from django-admin.py startproject) In urls.py:

import django.http.HttpResponse as r;urlpatterns=patterns(url(r'^*$',lambda q:r(status=418)))
\$\endgroup\$
1
\$\begingroup\$

C# + OWIN 251 240

I was really hoping it'd be shorter, but the long namespaces ruined that plan. Requires the Microsoft.Owin.SelfHost package available on NuGet.

using Owin;class P{static void Main(){Microsoft.Owin.Hosting.WebApp.Start<P>("http://localhost");while(0<1);}public void Configuration(IAppBuilder a){a.Run(c=>{c.Response.StatusCode=418;return System.Threading.Tasks.Task.FromResult(0);});}}
\$\endgroup\$
1
\$\begingroup\$

node.js with connect (78)

require('connect')().use(function(q,s,n){s.writeHead(418);s.end()}).listen(80)

You need to run npm install connect first. Then start it with node server.js

\$\endgroup\$
1
\$\begingroup\$

Go, 162 bytes

package main
import "net/http"
func main(){http.HandleFunc("/",func(w http.ResponseWriter,r *http.Request){w.WriteHeader(418)})
http.ListenAndServe(":80", nil)
}
\$\endgroup\$
1
\$\begingroup\$

Factor, 101 141 bytes

[ utf8 <threaded-server> readln 10 base> >>insecure [ "HTTP/1.1 418\r" print flush ] >>handler [ start-server ] in-thread start-server drop ]

Return 418 to everyone who connects.

\$\endgroup\$
1
\$\begingroup\$

Java 7, 208 bytes

import java.net.*;class R{public static void main(String[]a)throws Exception{for(ServerSocket s=new ServerSocket(80);;){Socket p=s.accept();p.getOutputStream().write("HTTP/1.0 418\n".getBytes());p.close();}}}

This question needed a java answer.

poke@server ~
$ curl -i localhost:80
HTTP/1.0 418
\$\endgroup\$
  • \$\begingroup\$ Where is status message? \$\endgroup\$ – Qwertiy Feb 28 '17 at 20:53
  • \$\begingroup\$ @Qwertiy I think this question only asks for status code which I interpret as the integer, so it follows that the status message/reason is not strictly required. \$\endgroup\$ – Poke Feb 28 '17 at 20:55
  • \$\begingroup\$ Not me to deside, but I think it should be with status text. \$\endgroup\$ – Qwertiy Feb 28 '17 at 20:58
  • 3
    \$\begingroup\$ Get Java 8 already >_> \$\endgroup\$ – Pavel Feb 28 '17 at 21:12
  • \$\begingroup\$ Here it is as a lambda for 148 bytes \$\endgroup\$ – Benjamin Urquhart Jul 21 at 22:22

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.