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.

Gnida
źródło
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)}}
człowiek w pracy
źródło
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
marinus
źródło
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.

primo
źródło
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
nyuszika7h
źródło
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

sierpień
źródło
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
Cyfrowa trauma
źródło
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
Trey Thomas
źródło
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
Qwertiy
źródło
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')
Tuomas Laakkonen
źródło
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}
Taylor Fausak
źródło
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
Cyfrowa trauma
źródło
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
człowiek w pracy
źródło
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()}
użytkownik2320464
źródło
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)
plannapus
źródło
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
cPu1
źródło
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'
Vi.
źródło
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
Sanchises
źródło
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ź”.

Ismael Miguel
źródło
-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

Knerd
źródło
2

nginx - 35

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

Rzuć to w nginx.conf, uruchom nginx.

Nie jestem pewien, czy wykorzystuje to standardowe luki „Używanie wbudowanych funkcji do wykonywania pracy” lub „Zbyt dosłowna interpretacja wyzwania”. Ups, wygląda na to, że OP nie spodoba się ta odpowiedź.

zamnuts
źródło
Czy nadal działałoby, jeśli upuściłeś ;?
Cyryl
+ 4 / -4: dobra robota w kontrowersjach: D
kot
2

Perl, 78

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

uruchomić jako plackup whatever.pl.

Hobbs
źródło
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)))
TheInitializer
źródło
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);});}}
Kok
źródło
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

Knerd
źródło
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)
}
ashooby
źródło
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ą.

kot
źródło
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
Szturchać
źródło
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
Oto jak lambda na 148 bajtów
Benjamin Urquhart