418: Я чайник


68

Як ми всі повинні знати, існує код статусу HTTP 418: Я чайник .

Якщо ви вирішите прийняти це, ваша місія полягає в тому, щоб використовувати свою творчість та написати найменший можливий сервер, який відповідає вищевказаним кодом статусу на будь-який запит HTTP, який було зроблено до нього.

Застосовуються стандартні лазівки , в т.ч.

Отримання потрібного виходу із зовнішнього джерела

Це включає виконання HTTP-запиту, щоб отримати сторінку із запитанням та витягнути рішення з цієї сторінки. Це було м'яко забавно ще в 2011 році, але зараз є похідним та нецікавим.

Це означає, що ви не можете просто перенаправити запит на інший сервер, щоб він повернув відповідь.


Виправлення певної плутанини щодо функціональності сервера:
Ваш сервер може робити що завгодно (або нічого), поки на нього не робиться запит HTTP, доки він не відповідає правильною відповіддю, коли буде зроблений запит HTTP.


15
до кожного запиту http? Безумовно, лише ті, хто на каву: URI?
Дейв

3
Чи можемо ми припустити, що у нас вже є привілеї root? (наприклад, прив’язати () до порту 80 нормально)
Digital Trauma

2
@DigitalTrauma Так, ви можете взяти на себе привілейовані ескалації для вашого сервера.
Ніт

4
@Knerd Я схиляюся з боку, ви не пишете програми, ви просто налаштовуєте її.
Ніт

2
О Боже мій. Коли IOT починається, цей код статусу може мати фактичну причину існування!
Світлий

Відповіді:


39

GNU Awk: 69 символів

Сам сервер (нескінченно обслуговує один запит за раз), не використовується бібліотека.

Надішліть 418 усім, хто підключається ( 82 69 символів):

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

Надішліть 418 кожному, хто щось надсилає ( 93 80 символів):

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

Надіслати 418 всім, хто надсилає дійсний HTTP GET-запит ( 122 109 символів):

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

Але .. як підключити? ;)
Оптимізатор

5
Таким же чином ви підключаєтесь до будь-якого веб-сервера. Браузер, netcat, telnet, wget, curl, інший GNU awkсценарій, ... Теоретично він прослуховує локального хоста: 80, але для того, що 1) немає веб - сервера, Skype або іншої програми , слід використовувати порт 80; 2) ви повинні бути суперкористувачем, щоб відкрити порти нижче 1024. Тож для тестування простіше відредагувати номер порту в скрипті на щось на зразок 8080 ( s="/inet/tcp/8080/0/0"), а потім підключитися до цього. pastebin.com/zauP7LMA
манатура

2
Я бачу. Класно. Awk noob here :)
Оптимізатор

1
Можливо, ви можете зберегти байт, використовуючи менший порт, наприклад 8, який не призначений.
Ганнес Карппіла

@HannesKarppila, це правильно. Але враховуючи, що всі інші рішення, які явно вказують порт (за винятком порту 8888 відповіді Haskell), використовують порт 80, я краще зберігати його таким чином для порівняння.
манатура

32

Баш (33)

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

3
Чи потрібні два нові рядки? Здається, працює добре з одним лише для мене. Також, по моєму рахунку, вище 34 байти - я здогадуюсь, що ваш редактор додає зайвий новий рядок або \0в кінець вашого файлу - ви можете truncateце зробити, і це все ще працює. s='echo HTTP/1.1 418|nc -lp80 -q1;$0' ; echo ${#s}дає для мене 33
Digital Trauma

@DigitalTrauma: Ви маєте рацію - остаточний рядок автоматично додається сюди рядками: Чому баш тут-рядка додає кінцевий знак нового рядка? ------ Але я бачу дві можливі проблеми: 1. Сценарій очікує, що він зберігається в одному з $PATHкаталогів або що він викликається шляхом (рекурсія по $0). ----- 2. HTTP вимагає, щоб лінії припинялися \r\nне тільки \n. Тут рядок повинен бути $"HTTP/1.1 418\r\n\r"(довше читабельна форма). ------ І нарешті: сценарій міг бути коротшим: -q1параметр не потрібен.
пабук

2
@DigitalTrauma, @pabouk: вихід повинен закінчуватися двома новими рядками. Отже, один з нових рядків був непотрібним (через рядок тут), але echoваріант не працює (принаймні Firefox не визнає його як 418). Однак \rs не потрібні. Спеціалізація каже, що так і має бути \r\n\r\n, але принаймні Firefox та Chrome приймуть \n\n, тому, здається, в дусі гольфу не включати їх. -q1Параметр необхідний в моїй системі, тому що браузер не закриє з'єднання самого по собі. $0добре працює, якщо сценарій зроблений виконуваним і викликаний таким чином.
marinus

@marinus Цікаво - я тестував, з wgetяким, здається, добре лише один новий рядок
Digital Trauma

1
@pabouk - Цікавий фрагмент тут w3.org/Protocols/HTTP/OldServers.html : "Лінії слід вважати припиненими каналом лінії, а попередній символ повернення перевезення ігнорується"
Digital Trauma

30

PHP - 85 байт

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

Збережено з кінцями рядків у стилі Windows (CR-LF), потрібно php_socketsувімкнути його.

Я фактично використовував це як свій код помилки для Hard Code Golf: Створення виклику в чаті , але ніхто не помітив.


Версія для веб-переглядача

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

Запустіть скрипт у CLI та вкажіть браузер на http://localhost.


1
+1 для користувача firendlyness / I'm a teapot:-)
Левіт

20

Node.js (LiveScript)

http модуль - 66

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

Натхненний відповіддю Квертія .

net модуль - 76

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

2
Чи міг би людина, котра поклонилася турботі, пояснити, чому?
nyuszika7h

20

Ruby + Rack, 19 байт

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

Потрібно зберегти як config.ruі запустити зrackup команду.

Або якщо ви віддаєте перевагу "чистий" Ruby:

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

42 байти + -rrackпрапор = 48 байт


12

Загальні команди Bash + BSD, 29

Позичити трохи від інших відповідей:

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

Для мене працює с wget .

Перша відповідь на використання nc, 38

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

Я припускаю кореневі привілеї - виконайте наступне:

sudo bash ./418.sh

3
@ ub3rst4r Правильно - саме тому я заявив "загальні команди BSD", які з точки зору сценаріїв оболонки можна вважати "бібліотекою". З ОП: "Всі бібліотеки вітаються"
Digital Trauma

2
Відповідь має закінчуватися символом нового рядка, см w3.org/Protocols/HTTP/Response.html
Nit

2
@Nit - Так - bash "тут рядки" автоматично додається до нового рядка
Digital Trauma

1
Як щодоnc -l 80 <<<HTTP/1.1\ 418;$0
core1024

1
Вибачте за плутанину з двох пробілів. Я не помітив, що ви не використовували -pкомутатор :) Я перевірив код з Firefox і без двох нових рядків код статусу не розпізнається.
пабук

9

Ruby (nc системна команда) - 35

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

DigitalTrauma має отримати кредит для ідеї використання nc , проте Ruby може зробити нескінченний цикл із меншою кількістю символів, ніж Bash :)

Ruby (TCPServer) - 75

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

Цей новий рядок є навмисним - фактичний символ нового рядка коротший, ніж "\ n".

Ruby (WEBrick HTTPServer) - 87

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

Відповідь має закінчуватися символом нового рядка, см w3.org/Protocols/HTTP/Response.html
Nit

1
@DigitalTrauma, я збирався використати це, але потім зрозумів, що відхилення від зворотного косого кута потрібно уникнути з іншим нахилом, так що все одно це було б однакова кількість символів :)
Trey Thomas

@TreyThomas О, я бачу - тому Рубі потрібен додатковий рівень втечі тут
Digital Trauma

8

Node.js, 80

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

Відповідь така

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
Мені здається, що просто дивовижно, що вузол спочатку підтримує цей код помилки ^^
Левіт

8

Пітон 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
На основі hallvabo «s коментар в Поради для гри в гольф в Python , from socket import*;s=socket(AF_INET,SOCK_STREAM)коротше.
манастирство

@manatwork Спасибі, чи існує коротший спосіб нескінченного циклу? Я не знайшов жодної у підказках ...
Tuomas Laakkonen

3
while 1:s.accept()[0].sendall(bytes('HTTP/1.1 418\n','UTF8'))- якщо я щось не пропустив. (До речі, не соромтеся рахувати нові рядки поодинокими символами, оскільки мова дозволяє. Таким чином ви нічого не втрачаєте, розділяючи команди замість рядків замість ;.)
манатура

Ви можете відрізати 2 символи, вважаючи, що порт 80 доступний, відповідно до коментаря власника питання . Одна потворна річ, яка може порушити портативність, але тут може бути прийнятною: використовувати значення констант безпосередньо s=socket(2,1)(принаймні, це їх значення в моєму Linux).
манатурка

У документації для listen()параметра 's зазначається, що «максимальне значення залежить від системи (зазвичай 5)». Тож замість 10, 9 більше, ніж достатньо, а на 1 символ коротше. І замість bytes('HTTP/1.1 418\n','UTF8')буквального b'HTTP/1.1 418\n'достатньо. Або якщо ви робите код Python 2, то bбайтпрефікс більше не потрібен. І коротшого send()теж здається, що достатньо.
манатура

7

Haskell - 142 байти

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 байт

Редагувати - додано в додатковий новий рядок (всього 2 нові рядки) задля відповідності.

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

Відповідь має закінчуватися новим рядком, див. W3.org/Protocols/HTTP/Response.html
Nit

3
@Nit - Так, Tcl ставить автоматично додавання нового рядка, якщо не вказано параметр -nenewline. tcl.tk/man/tcl/TclCmd/puts.htm
Digital Trauma

5

Юлія: 86 73 символи

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

")
close(c)
end

Я не думаю, що вам потрібна справжня частина "Я чайник" - коду відповіді має бути достатньо.
Десті

Так, я це помітив. Але оскільки це не дуже допоможе в оцінці Джулії, я продовжував її завершувати. Але, напевно, було б краще її зняти, щоб полегшити порівняння мов.
манатурка

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 символів

Ніколи раніше не робив програмування сокет з R, але спробую:

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

Тут socketConnectionвідкривається сокет: першим аргументом повинен бути хост, за замовчуванням localhostми можемо пропустити його тут; другий аргумент - порт, який не має за замовчуванням, тоді аргумент, serverколи зазначено, TRUEстворює сокет, якщо FALSEвін просто підключається до існуючого. Tза замовчуванням дорівнює TRUE, у Р.

Редагувати: Як пропонується в запропонованій редакцією @AlexBrown, це може бути скорочено до 69 символів :

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

4

Node.js koa , 61 Байт

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

Відповідь:

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

Потрібен вузол v0.11.12 +

Виконувати як:

node --harmony app.js

Що function*?
nyuszika7h

2
Це функція генератора , що є частиною пропозиції ECMAScript 6, Гармонія.
cPu1

4

Shell + сокат, 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\rкоротше.
jimmy23013

Це \\ Tнавіть не потрібно.
nyuszika7h

3

MATLAB, 97 86 байт

Насправді не серйозний претендент з точки зору абсолютного підрахунку байтів, але я хотів би опублікувати його, тому що я не думав, що можна буде написати повністю функціональний веб-сервер за допомогою математичного інструменту. Зверніть увагу на використання скорочення властивості : 'Ne','s'внутрішньо розширюється до '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

Це можна зробити з мінімальними зусиллями, використовуючи .htaccessфайл та php.

Усі звернення до вашого сервера повернуть статус 418.

Нижче наведено код:

.htaccess (28 байт)

RewriteRule .* index.php [L]

PHP ( 38 19 байт)

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

Дякую @primo за те, що врятував мені купу байтів!


Я перевірив це і підтверджую, що він повертає бажаний результат!

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

До речі, "Педідо" означає "Запит", а "Відповідь" - "Відповідь".


-1, це не повна програма. Він покладається на зовнішній веб-сервер.
nyuszika7h

@ nyuszika7h Насправді він покладається на Apache з PHP, встановленим як модуль. Ваш аргумент є дійсним і недійсним. Apache лише перенаправляє доступ до файлу PHP, файл PHP піклується про код.
Ісмаїл Мігель

@ nyuszika7h Якщо ми перейдемо на цей шар, то ви навіть не можете використовувати консоль для запуску PHP-коду. Apache - це стартер. Спусковий гачок, що стріляє кулею. Запуск файла PHP з консолі зробить консоль тригером.
Ісмаїл Мігель

Ви покладаєтесь на те, що Apache вже працює, і я не думаю, що він буде працювати без зміни конфігурації за замовчуванням. Мені все одно, що ти кажеш, я не можу вважати це дійсним. Але вам слід запитати @Nit, оскільки це їх питання.
nyuszika7h

@ nyuszika7h Якби він був недійсним, ОП сказав би вже.
Ісмаїл Мігель

2

node.js з CoffeeScript (76)

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

Просто компілюйте його в JavaScript, тоді вам потрібно запустити npm install connect. Після цього починайте йогоnode server.js


2

nginx - 35

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

Киньте це в nginx.conf, запустіть nginx.

Не впевнений, що для цього використовуються стандартні лазівки "Використання вбудованих функцій для виконання роботи" або "Тлумачення виклику занадто буквально". На жаль, ОП не сподобається цій відповіді.


Чи все-таки спрацює, якби ви кинули ;?
Кирило

+ 4 / -4: молодець у полеміці: D
кіт

2

Перл, 78

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

бігти як plackup whatever.pl.


Якщо ви хочете, щоб застосувати набір, тоді просто sub{[418,[],[]]}повинно бути достатньо. (16 символів.)
tobyink

Звичайно, ти маєш рацію! Це не так, як я використовую будь-який з фреймворків, навіщо його завантажувати? :)
хобби

@tobyink не соромтеся подати це як власне :)
hobbs

2

Python 2.7 / Django, 94 байти

(додано з django-admin.py startprojectкотла за замовчуванням від ) У urls.py:

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

1

C # + ВЛАСНІ 251 240

Я дуже сподівався, що це буде коротше, але довгі простори імен зруйнували цей план. Потрібен Microsoft.Owin.SelfHostпакет, доступний на 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 з підключенням (78)

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

Вам потрібно запустити npm install connectпершим. Потім почніть з цьогоnode server.js


1

Ідіть, 162 байти

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

1

Фактор, 101 141 байт

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

Поверніть 418 усім, хто підключиться.


1

Java 7, 208 байт

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

На це запитання потрібна відповідь java.

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

Де знаходиться повідомлення про стан?
Qwertiy

@Qwertiy Я думаю, що це запитання задає лише код статусу, який я трактую як ціле число, тому випливає, що повідомлення / причина статусу не є строго обов'язковим.
Поп

Я не для відмови, але я думаю, що це має бути з текстом статусу.
Qwertiy

3
Отримайте Java 8 вже> _>
Павло

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.