418: Jestem czajnikiem


68

Jak wszyscy powinniśmy wiedzieć, istnieje kod statusu HTTP 418: Jestem czajnikiem .

Twoja misja, jeśli zdecydujesz się ją zaakceptować, polega na użyciu creativitea i napisaniu najmniejszego możliwego serwera, który odpowiada powyższym kodem stanu na każde wysłane do niego żądanie HTTP.

Obowiązują standardowe luki , w tym

Pobieranie żądanego wyjścia z zewnętrznego źródła

Obejmuje to wykonanie żądania HTTP w celu pobrania strony z pytaniem i wyodrębnienie rozwiązania z tej strony. To było nieco zabawne w 2011 roku, ale teraz jest pochodne i nieciekawe.

Oznacza to, że nie można po prostu przekierować żądania na inny serwer, aby zwrócił odpowiedź.


Rozwiązanie niektórych problemów związanych z funkcjonowaniem serwera:
Twój serwer może zrobić wszystko (lub nic), dopóki nie zostanie do niego wysłane żadne żądanie HTTP, o ile odpowie prawidłową odpowiedzią po wysłaniu żądania HTTP.


15
na każde żądanie HTTP? Z pewnością tylko na kawę: URI?
dave

3
Czy możemy założyć, że mamy już uprawnienia roota? (np. bind () do portu 80 jest w porządku)
Digital Trauma

2
@DigitalTrauma Tak, możesz przejąć eskalowane uprawnienia dla swojego serwera.
Nit

4
@ Knerd Opieram się na niczym, nie piszesz programu, po prostu go konfigurujesz.
Nit

2
o mój Boże. Wraz z nadejściem IOT ten kod statusu może mieć rzeczywisty powód do istnienia!
Luminous

Odpowiedzi:


39

GNU Awk: 69 znaków

Sam serwer (bez końca obsługuje jedno żądanie na raz), bez użycia biblioteki.

Wyślij 418 do każdego, kto się łączy ( 82 69 znaków):

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

Wyślij 418 do wszystkich, którzy coś wysyłają ( 93 80 znaków):

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

Wyślij 418 do wszystkich, którzy wysyłają prawidłowe żądanie HTTP GET ( 122 109 znaków):

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)}}

Ale .. jak się połączyć? ;)
Optymalizator

5
W ten sam sposób łączysz się z dowolnym serwerem WWW. Przeglądarka, netcat, telnet, wget, curl, GNU inny awkscenariusz ... Teoretycznie nasłuchuje na localhost: 80, ale w tym 1) Nie ma serwera WWW, Skype lub inny program powinien używać portu 80; 2) musisz być superużytkownikiem, aby otwierać porty poniżej 1024. Więc do testowania łatwiej jest edytować numer portu w skrypcie na coś takiego jak 8080 ( s="/inet/tcp/8080/0/0"), a następnie połączyć się z tym. pastebin.com/zauP7LMA
manatwork

2
Widzę. Chłodny. Awk noob tutaj :)
Optymalizator

1
Możesz zapisać bajt, używając mniejszego portu, takiego jak 8, który jest nieprzypisany.
Hannes Karppila

@HannesKarppila, zgadza się. Ale biorąc pod uwagę, że wszystkie inne rozwiązania, które jednoznacznie określają port (oprócz portu 8888 odpowiedzi Haskella) używają portu 80, lepiej dla zachowania porównywalności.
manatwork

32

Bash (33)

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

3
Czy potrzebne są dwie nowe linie? Wygląda na to, że działa OK tylko z jednym dla mnie. Według moich obliczeń powyższe ma 34 bajty - domyślam się, że twój edytor dodaje niepotrzebną nową \0linię lub na końcu pliku - możesz truncateto zrobić i nadal działa. s='echo HTTP/1.1 418|nc -lp80 -q1;$0' ; echo ${#s}daje 33 dla mnie
Digital Trauma

@DigitalTrauma: Masz rację - końcowa nowa linia jest automatycznie dodawana tutaj ciągów: Dlaczego ciąg bash tutaj dodaje końcowy znak nowej linii? ------ Ale widzę dwa możliwe problemy: 1. Skrypt oczekuje, że jest przechowywany w jednym z $PATHkatalogów lub że jest wywoływany ze ścieżką (rekursja przez $0). ----- 2. HTTP wymaga, aby linie były kończone \r\nnie tylko \n. Tutaj powinien być ciąg $"HTTP/1.1 418\r\n\r"(forma czytelniejsza). ------ Wreszcie: skrypt może być krótszy: -q1parametr nie jest konieczny.
pabouk

2
@DigitalTrauma, @pabouk: Dane wyjściowe muszą kończyć się dwoma nowymi wierszami. Tak więc jeden z nowych wierszy był niepotrzebny (ze względu na ciąg tutaj), ale echowariant nie działa (przynajmniej Firefox nie rozpozna go jako 418). Jednak \rnie są potrzebne. Specyfikacja mówi, że tak powinno być \r\n\r\n, ale przynajmniej Firefox i Chrome zaakceptują \n\n, więc wydaje się, że w duchu golfa ich nie ma. Ten -q1parametr był konieczny w moim systemie, ponieważ przeglądarka sama nie zamknie połączenia. $0działa dobrze, jeśli skrypt jest wykonywalny i wywoływany w ten sposób.
marinus

@marinus Ciekawe - testowałem, z wgetktórym wydaje się być w porządku tylko z jedną nową linią
Digital Trauma

1
@pabouk - Interesujący fragment tutaj w3.org/Protocols/HTTP/OldServers.html : „Linie powinny być traktowane jako zakończone przez Line Feed, a poprzedzający znak powrotu karetki zignorowany”
Trauma cyfrowa

30

PHP - 85 bajtów

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

Zapisane z zakończeniami linii w stylu Windows (CR-LF), wymaga php_socketswłączenia.

Użyłem tego jako mojego kodu błędu w Hard Code Golf: Utwórz wyzwanie na czacie , ale nikt tego nie zauważył.


Wersja przyjazna dla przeglądarki

<?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);

Uruchom skrypt w CLI i skieruj przeglądarkę na http://localhost.


1
+1 za firendlyness użytkownika / I'm a teapot:-)
Levit

20

Node.js (LiveScript)

http moduł - 66

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

Zainspirowany odpowiedzią Qwertiy .

net moduł - 76

require(\net)createServer (->it.write 'HTTP/1.1 418\r\n';it.end!) .listen 80

2
Czy osoba, która przegłosowała głos, może wyjaśnić, dlaczego?
nyuszika7h

20

Ruby + Rack, 19 bajtów

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

Należy zapisać jako config.rui uruchomić z rackuppoleceniem.

Lub jeśli wolisz „czysty” Ruby:

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

42 bajty + -rrackflaga = 48 bajtów


12

Ogólne polecenia Bash + BSD, 29

Pożyczając trochę od innych odpowiedzi:

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

Działa dla mnie z wget.

Pierwsza odpowiedź do użycia nc, 38

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

Przyjmuję uprawnienia roota - uruchom w następujący sposób:

sudo bash ./418.sh

3
@ ub3rst4r Prawidłowo - dlatego powiedziałem „ogólne polecenia BSD”, które z punktu widzenia skryptów powłoki można uznać za „bibliotekę”. Z PO: „Wszystkie biblioteki są mile widziane”
Digital Trauma

2
Odpowiedź musi kończyć się nową linią, patrz w3.org/Protocols/HTTP/Response.html
Nit

2
@Nit - Tak - bash „tu strings” zostanie automatycznie dodany z nową linią
Digital Trauma

1
Co powiesz nanc -l 80 <<<HTTP/1.1\ 418;$0
core1024,

1
Przepraszam za zamieszanie z dwoma spacjami. Nie zauważyłem, że nie używałeś -pprzełącznika :) Testowałem kod w Firefoksie i bez dwóch nowych linii kod statusu nie jest rozpoznawany.
pabouk

9

Ruby (polecenie systemowe nc) - 35

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

DigitalTrauma powinna docenić pomysł użycia nc, jednak Ruby może wykonać nieskończoną pętlę z mniejszą liczbą znaków niż Bash :)

Ruby (TCPServer) - 75

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

Ta nowa linia jest zamierzona - rzeczywisty znak nowej linii jest o jeden znak krótszy niż „\ n”.

Ruby (WEBrick HTTPServer) - 87

require'webrick'
(s=WEBrick::HTTPServer.new).mount_proc(?/){|_,r|r.status=418}
s.start

Odpowiedź musi kończyć się nowym wierszem
Nit

1
@DigitalTrauma, miałem zamiar użyć jej, ale potem zrozumiał, że odwrotny ukośnik należy uciekł z inną backslashem, więc to byłaby taka sama liczba znaków w każdym razie :)
Trey Thomas

@TreyThomas Och, rozumiem - więc Ruby potrzebuje tutaj dodatkowego poziomu ucieczki
Digital Trauma

8

Node.js, 80

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

Odpowiedź brzmi:

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

0

2
Uważam, że to niesamowite, że węzeł obsługuje ten kod błędu natywnie ^^
Levit

8

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')

1
Na podstawie hallvabo „s komentarzu w Porady dla golfa w Pythonie , from socket import*;s=socket(AF_INET,SOCK_STREAM)jest krótszy.
manatwork

@manatwork Dzięki, czy istnieje krótsza droga do nieskończonej pętli? Nie znalazłem żadnego z porad ...
Tuomas Laakkonen,

3
while 1:s.accept()[0].sendall(bytes('HTTP/1.1 418\n','UTF8'))- chyba że coś przeoczyłem. (Nawiasem mówiąc, nie krępuj się liczyć nowego wiersza pojedynczych znaków, jak pozwala na to język. W ten sposób nic nie tracisz, oddzielając polecenia ;
znakiem

Możesz odciąć 2 znaki, zakładając, że port 80 jest dostępny, zgodnie z komentarzem właściciela pytania . Jedna brzydka rzecz, która może zepsuć przenośność, ale może być tutaj do przyjęcia: użyj wartości stałych bezpośrednio s=socket(2,1)(przynajmniej takie są ich wartości w moim systemie Linux).
manatwork

Dokumentacja mówi dla listen()parametru, że „maksymalna wartość zależy od systemu (zwykle 5)”. Zamiast 10, 9 to więcej, a 1 postać jest krótsza. I zamiast bytes('HTTP/1.1 418\n','UTF8')literału b'HTTP/1.1 418\n'wystarczy. Lub jeśli bstworzysz kod Python 2, to bytesprefix nie jest już potrzebny. I krótszy send()też wydaje się wystarczający.
manatwork

7

Haskell - 142 bajty

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}

5

Tcl (> = 8,5), 78 bajtów

Edycja - dodany w dodatkowym nowym wierszu (łącznie 2 nowe wiersze) ze względu na zgodność.

socket -server {apply {{c - -} {puts $c "HTTP/1.1 418
";close $c}}} 80
vwait f

Odpowiedź musi kończyć się nową linią, patrz w3.org/Protocols/HTTP/Response.html
Nit

3
@Nit - Tak, wstawki Tcl automatycznie dołączą nowy wiersz, chyba że podano opcję -nonewline. tcl.tk/man/tcl/TclCmd/puts.htm
Cyfrowa trauma

5

Julia: 86 73 znaków

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

")
close(c)
end

Nie sądzę, żebyś potrzebował części „Jestem czajnikiem” - kod odpowiedzi powinien wystarczyć.
Desty

Tak, zauważyłem to. Ale ponieważ niewiele to pomoże w wynikach Julii, dopełniłem go. Ale prawdopodobnie lepiej byłoby go usunąć, aby ułatwić porównanie języków.
manatwork

5

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()}

5

R, 80 znaków

Nigdy wcześniej nie programowałem w gniazdach za pomocą R, ale spróbuję:

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

Tutaj socketConnectionotwiera się gniazdo: pierwszym argumentem powinien być host, domyślnie localhostmożemy to pominąć tutaj; drugi argument to port, który nie ma wartości domyślnej, a następnie argument, servergdy jest określony, TRUEtworzy gniazdo, jeśli FALSEpo prostu łączy się z istniejącym. Tjest domyślnie równe TRUER.

Edycja: Jak sugeruje sugerowana edycja @AlexBrown, można ją skrócić do 69 znaków :

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

4

Node.js koa , 61 bajtów

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

Odpowiedź; reakcja; reagowanie; odzew; oddźwięk:

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

Wymaga węzła v0.11.12 +

Uruchom jako:

node --harmony app.js

Co jest function*?
nyuszika7h

2
To funkcja generatora , część ECMAScript 6, propozycja Harmony.
cPu1

4

Shell + socat, 60

socat tcp-l:80,fork exec:'printf HTTP/1.1\\ 418\\ T\r\n\r\n'

echo -e HTTP/1.1 418 T\r\n\rjest krótszy.
jimmy23013,

To \\ Tnawet nie jest potrzebne.
nyuszika7h

3

MATLAB, 97 86 bajtów

Nie jest to poważny konkurent pod względem całkowitej liczby bajtów, ale chciałbym to opublikować, ponieważ nie sądziłem, że można napisać w pełni funkcjonalny serwer WWW za pomocą narzędzia matematycznego. Zwróć uwagę na użycie skrótu własności : 'Ne','s'wewnętrznie rozwija się do 'NetworkRole', 'server'.

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

3

Możesz to zrobić przy minimalnym wysiłku, używając .htaccesspliku i php.

Wszystkie dostępy do twojego serwera zwrócą status 418.

Poniżej znajduje się kod:

.htaccess (28 bajtów)

RewriteRule .* index.php [L]

PHP ( 38 19 bajtów)

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

Dzięki @primo za uratowanie mi kilku bajtów!


Przetestowałem to i potwierdzam, że zwraca pożądany wynik!

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

Nawiasem mówiąc, „Pedido” oznacza „Zapytanie”, a „Resposta” oznacza „Odpowiedź”.


-1, to nie jest kompletny program. Opiera się na zewnętrznym serwerze internetowym.
nyuszika7h

@ nyuszika7h W rzeczywistości opiera się na Apache z PHP zainstalowanym jako moduł. Twój argument jest ważny i nieważny. Apache przekierowuje tylko dostęp do pliku PHP, plik PHP zajmuje się kodem.
Ismael Miguel

@ nyuszika7h Jeśli zejdziemy na tę warstwę, nie możesz nawet użyć konsoli do uruchomienia kodu PHP. Apache jest starterem. Spust, który wystrzeliwuje pocisk. Uruchomienie pliku PHP z konsoli spowoduje uruchomienie konsoli.
Ismael Miguel

Polegasz na tym, że Apache już działa i nie sądzę, aby działał bez zmiany domyślnej konfiguracji. Nie obchodzi mnie, co mówisz, nie ma mowy, żebym uważał to za ważne. Ale powinieneś zapytać @Nit, bo to ich pytanie.
nyuszika7h

@ nyuszika7h Gdyby był nieważny, OP powiedziałby już.
Ismael Miguel

2

node.js z CoffeeScript (76)

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

Wystarczy skompilować go w JavaScript, a następnie trzeba uruchomić npm install connect. Następnie zacznij odnode server.js



2

Perl, 78

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

uruchomić jako plackup whatever.pl.


Jeśli chcesz mieć aplikację typu plack, to po prostu sub{[418,[],[]]}powinno wystarczyć. (16 znaków)
tobyink

Oczywiście masz rację! To nie tak, że używam żadnego frameworka, po co go ładować? :)
hobbs

@tobyink zachęcamy do przesłania go jako własnego :)
hobbs

2

Python 2.7 / Django, 94 bajty

(dodany z domyślnej płyty głównej z django-admin.py startproject) W urls.py:

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

1

C # + OWIN 251 240

Naprawdę miałem nadzieję, że będzie krótszy, ale długie przestrzenie nazw zrujnowały ten plan. Wymaga Microsoft.Owin.SelfHostpakietu dostępnego w 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);});}}

1

node.js with connect (78)

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

npm install connectNajpierw musisz biec . Następnie zacznij odnode server.js


1

Idź, 162 bajty

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

1

Współczynnik, 101 141 bajtów

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

Zwróć 418 wszystkim, którzy się łączą.


1

Java 7, 208 bajtów

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();}}}

To pytanie wymagało odpowiedzi w języku Java.

poke@server ~
$ curl -i localhost:80
HTTP/1.0 418

Gdzie jest komunikat o stanie?
Qwertiy

@Qwertiy Myślę, że to pytanie wymaga jedynie kodu statusu, który interpretuję jako liczbę całkowitą, więc wynika z tego, że komunikat o stanie / przyczyna nie jest ściśle wymagany.
Poke

Nie do mnie, ale myślę, że powinno być z tekstem statusu.
Qwertiy

3
Pobierz Java 8 już> _>
Pavel

Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.