Сегодня я не в первый раз задался вопросами: какие языки программирования пригодны для веба, и имеет ли смысл решать какую-то узкую задачу способом, который на первый взгляд для этого не подходит? Мне захотелось попрактиковаться, сделав что-нибудь обычное необычным способом.
Для чего?
Я задался целью написать вебприложение целиком на языке матлаба без использования каких-либо обёрток. Зачем я стал это делать? Здесь есть несколько причин. Мне показалось это просто забавным. Помимо этого я наблюдал, как многие вебпрограммисты склоняются в своей работе к каким-то стереотипным решениям, что можно было бы назвать «PHP головного мозга». Это сказано ни в коем случае не в укор php-программистам, просто такое явление есть и я думаю, что моя заметка будет кому-то примером.
Как?
В качестве интерпретатора этого языка я выбрал GNU Octave по причине его бесплатности и лёгкодоступности на линуксе. В качестве вебсервера я выбрал nginx по той причине, что много работаю с ним и мне он просто очень удобен. Мне нужно было заставить работать скрипт на матлабе как CGI-приложение. В юниксах есть для этого простая возможность — вначале текстового файла можно указать путь и параметры интерпретатора и если у файла стоит атрибут выполнимости, он может быть запущен и будет выполнен посредством этого интерпретатора. Сам по себе nginx не умеет выполнять простые CGI и примеры врапперов отсюда мне НЕ помогли. В другом источнике, не столь приближённом к создателям вебсервера, было предложено использовать для nginx fcgiwrapper, который даже входит в состав моего дистрибутива debian.
Что получилось?
Фрагмент итоговой конфигурации nginx:
location ~ \.m$ {
gzip off; #gzip makes scripts feel slower since they have to complete before getting gzipped
fastcgi_pass unix:/var/run/fcgiwrap.socket;
fastcgi_index index.m;
fastcgi_param SCRIPT_FILENAME /var/www/m.leprodc$fastcgi_script_name;
fastcgi_param QUERY_STRING $query_string;
fastcgi_param REQUEST_METHOD $request_method;
fastcgi_param CONTENT_TYPE $content_type;
fastcgi_param CONTENT_LENGTH $content_length;
fastcgi_param GATEWAY_INTERFACE CGI/1.1;
fastcgi_param SERVER_SOFTWARE nginx;
fastcgi_param SCRIPT_NAME $fastcgi_script_name;
fastcgi_param REQUEST_URI $request_uri;
fastcgi_param DOCUMENT_URI $document_uri;
fastcgi_param DOCUMENT_ROOT $document_root;
fastcgi_param SERVER_PROTOCOL $server_protocol;
fastcgi_param REMOTE_ADDR $remote_addr;
fastcgi_param REMOTE_PORT $remote_port;
fastcgi_param SERVER_ADDR $server_addr;
fastcgi_param SERVER_PORT $server_port;
fastcgi_param SERVER_NAME $server_name;
}
Код скрипта plot1.m:
#!/usr/bin/octave -q
domain="m.leprodc.ru";
ARG=sscanf(getenv("QUERY_STRING"),"a=%g&b=%g&c=%g");
if (length(ARG)==3)
a=ARG(1);
b=ARG(2);
c=ARG(3);
handle=figure;
X=-10:0.1:10;
Y=a.*X.^2+b.*X+c;
printf("Content-type: text/plain\n\n");
plot(X,Y);
print(handle, sprintf('/tmp/plot-%s:%s.png',getenv("REMOTE_ADDR"),getenv("REMOTE_PORT")),'-dpng');
printf("Full image: http://%s/plot-%s:%s.png\n\n",domain,getenv("REMOTE_ADDR"),getenv("REMOTE_PORT"));
else
printf("Location: http://%s/\n\n",domain);
endif
Что получилось?
Например, вот: http://m.leprodc.ru/