Автор Тема: Задача 2 - 10.09 - 16.09 - quotes web service  (Прочетена 104921 пъти)

BULFON

  • Administrator
  • Участник
  • *****
  • Публикации: 478
  • Distribution: Fedora
  • Window Manager: Gnome
    • Профил
Задача 2 - 10.09 - 16.09 - quotes web service
« -: Сеп 11, 2007, 13:58 »
Да се напише скрипт (скриптове, програми), които работят като web service. Т.е. "слушат" на някой порт за заявка (HTTP) и отговарят. Целта е произведеното от тях да може лесно да бъде консумирано от различни други уеб услуги или сайтове.
В случая може да се ползва директно изхода от програми като fortune, рибата в гном или всякакви такива. Може и да работи с MySQL база данни с вицове за Чапай и Петка (някой има ли такава база). Изходът е добре да може да се избира - дали да е text/plain, applications/json (JSON - формат), application/xml. Сигурност не е нужна, но ако се реализира някаква схема за изибирателен достъп ще е плюс, за да не се закачат много маймуни. Логване на заявките също ще е добре да има.
Активен

фонокартен телефонен апарат

gat3way

  • Участник
  • *****
  • Публикации: 6050
  • Relentless troll
    • Профил
    • WWW
Задача 2 - 10.09 - 16.09 - quotes web service
« Отговор #1 -: Сеп 11, 2007, 14:24 »
Мамка му '<img'>

Разширете малко срока, бе хора '<img'>

С 2-3 дена
'<img'>

На 15 си кацам в София и ще мога да се включа '<img'>
Активен

"Knowledge is power" - France is Bacon

BULFON

  • Administrator
  • Участник
  • *****
  • Публикации: 478
  • Distribution: Fedora
  • Window Manager: Gnome
    • Профил
Задача 2 - 10.09 - 16.09 - quotes web service
« Отговор #2 -: Сеп 11, 2007, 14:45 »
Заради нашия редовен участник, конкура се удължен до 19ти '<img'>.
Активен

фонокартен телефонен апарат

gat3way

  • Участник
  • *****
  • Публикации: 6050
  • Relentless troll
    • Профил
    • WWW
Задача 2 - 10.09 - 16.09 - quotes web service
« Отговор #3 -: Сеп 11, 2007, 15:07 »
Е хубаво, ако едно участие е редовно '<img'>

Много обичам да пиша сокет приложения на С, всъщност всичко което пратя ще бъде или на С или на PHP, шел скиптовете не са ми особено голяма сила '<img'>
Активен

"Knowledge is power" - France is Bacon

VladSun

  • Moderator
  • Участник
  • *****
  • Публикации: 2166
    • Профил
Задача 2 - 10.09 - 16.09 - quotes web service
« Отговор #4 -: Сеп 11, 2007, 15:24 »
Цитат (gat3way @ Сеп. 11 2007,15:07)
Е хубаво, ако едно участие е редовно '<img'>

1/1 са си цели 100% '<img'>



Активен

KISS Principle ( Keep-It-Short-and-Simple )
http://openfmi.net/projects/flattc/
Има 10 вида хора на този свят - разбиращи двоичния код и тези, които не го разбират :P

gat3way

  • Участник
  • *****
  • Публикации: 6050
  • Relentless troll
    • Профил
    • WWW
Задача 2 - 10.09 - 16.09 - quotes web service
« Отговор #5 -: Сеп 11, 2007, 15:34 »
'<img'>
Активен

"Knowledge is power" - France is Bacon

VladSun

  • Moderator
  • Участник
  • *****
  • Публикации: 2166
    • Профил
Задача 2 - 10.09 - 16.09 - quotes web service
« Отговор #6 -: Сеп 11, 2007, 17:01 »
FIRST!

pwww.pl
Примерен код

#!/usr/bin/perl -w
package WWWServer;

use Sys::Syslog;      
use base qw(Net::Server::Fork);
@ISA = qw(Net::Server::Fork);

our @acceptedTypes = ('text/html', 'applications/json', 'application/xml', );

sub process_request
{
    my $self = shift;
    my $service = 0;
    my $type = $acceptedTypes[0];


    while (<STDIN>)
    {
        s/\r?\n$//;

        if (m/GET \/(\w+) HTTP\/(1.1|1.0)/i)
        {
            if ($1 eq 'time')
            {
                syslog("info", "Service request: TIME");
                $service = 1;
            }
            elsif ($1 eq 'fortune')
            {
                syslog("info", "Service request: FORTUNE");
                $service = 2;
            }
            else
            {
                syslog("info", "Service not found");
            }
        }
        if (m/Accept:\s+\w+/i)
        {
            foreach my $accepted_type (@acceptedTypes)
            {
                if (/$accepted_type/)
                {
                    $type = $accepted_type;
                    last;
                }
            }
        }
        if ($_ eq '')
        {
            last;
        }
    }
    if ($service)
    {
        print "HTTP/1.1 200 OK\r\n";
        print "Content-Type: $type\r\n";
        print "Server: PWWW Server\r\n";
        print "Connection: close\r\n";
        print "\r\n";
        if ($service == 1)
        {
            print `/usr/bin/date`."\r\n";
        }
        elsif ($service == 2)
        {
            print `/usr/games/fortune`."\r\n";
        }
    }
    else
    {
        print "HTTP/1.1 400 Bad Request\r\n";
        print "Server: PWWW Server\r\n";
        print "Connection: close\r\n";
        print "\r\n";
        print "Not implemented.";
    }
}

my $server  = new WWWServer({conf_file => 'pwww.conf',});

$server->run();


pwww.conf
Примерен код

user            www
group           www

log_file        Sys::Syslog
log_level       4
syslog_logopt   pid,ndelay,nowait
syslog_ident    pwww

pid_file        pwww.pid

port            160
host            *

cidr_allow    192.168.0.0/16
cidr_allow    10.10.0.0/16
cidr_deny    192.168.1.0/24

background      1
setsid          1



EDIT: Малка грешка за content-type-a '<img'>



Активен

KISS Principle ( Keep-It-Short-and-Simple )
http://openfmi.net/projects/flattc/
Има 10 вида хора на този свят - разбиращи двоичния код и тези, които не го разбират :P

Hapkoc

  • Участник
  • *****
  • Публикации: 2117
    • Профил
Задача 2 - 10.09 - 16.09 - quotes web service
« Отговор #7 -: Сеп 11, 2007, 17:16 »
Примерен код

$ cat shttpd.sh
#! /bin/bash

### http functions

function send_response_headers {
        code="$1"

        # access logging
        code_num=$(echo $code | cut -d' ' -f1)
        date=$(date '+[%d/%b/%Y:%T %z]')
        echo "$REMOTE_HOST - - $date \"$method $url $proto\" $code_num 0 \"$referer\" \"$user_agent\"" >> /var/log/shttpd/access_log

        echo "HTTP/1.0 $code"
        echo "Date: " $(date -uR | sed -e 's/+0000/GMT/')
        echo "Connection: close"
        echo "Content-type: text/plain; charset=utf-8"
        echo "Server: shttpd"
        echo ""
}

### main program

method=""
url=""
proto=""
referer=""
user_agent=""

line_no=1
while read line; do
        # clean up ending ^M
        line=$(echo $line | head --bytes=-2)

        # check if this is the last header
        echo "$line" | grep -E '^\s*$' >/dev/null 2>&1 && break

        # get the request line
        if [ "$line_no" -eq 1 ]; then
                method=$(echo "$line" | awk '{ print $1 }')
                url=$(echo "$line" | awk '{ print $2 }')
                proto=$(echo "$line" | awk '{ print $3 }')
        # check the headers
        else
                header=$(echo "$line" | cut -d' ' -f1)
                header_contents=$(echo "$line" | cut -d' ' -f2-)

                case "$header" in
                        Referer:*) referer="$header_contents";;
                        User-Agent:*) user_agent="$header_contents";;
                        *);;
                esac
        fi

        let line_no=$((line_no + 1))
done

# verify whether the access is allowed
if [ -r "/etc/shttpd.d/access_list" ]; then
        grep -E "^$REMOTE_HOST$" /etc/shttpd.d/access_list >/dev/null 2>&1 || {
                send_response_headers "403 Forbidden"
                echo "403 Forbidden"
                exit
        }
fi

# verify the method and url
if [ -z "$method" ] || [ -z "$url" ]; then
        send_response_headers "400 Bad Request"
        echo "400 Bad Request"
fi

# send the reply
case "$method" in
        "GET" | "POST")
                send_response_headers "200 OK"
                /usr/games/fortune
                ;;
        "HEAD")
                send_response_headers "200 OK"
                ;;
        *)
                send_response_headers "405 Method Not Allowed"
                echo "405 Method Not Allowed"
                ;;
esac

exit




Примерен код

# cat /etc/xinetd.d/shttpd
service www
{
        type            = UNLISTED
        disable         = no
        socket_type     = stream
        protocol        = tcp
        port            = 8081
        wait            = no
        user            = nobody
        group           = nogroup
        server          = /usr/local/bin/shttpd.sh
}


В /etc/shttpd.d/access_list се описват IP адресите, които могат да достъпват нещото. /var/log/shttpd/access_log е (както подсказва името) access log-а. :)

Не гарантирам за пълно спазване на HTTP/1.1. :)



Активен

the_real_maniac

  • Участник
  • *****
  • Публикации: 1258
  • Kernel panic, me - no panic ;-) :-)
    • Профил
Задача 2 - 10.09 - 16.09 - quotes web service
« Отговор #8 -: Сеп 11, 2007, 21:36 »
Цитат (VladSun @ Сеп. 11 2007,18:01)
FIRST!

offtopic:

Примерен код

F U C K !


 '<img'>  '<img'>  '<img'>  '<img'>  ':p'  'B)'  '<img'>  '<img'>

http://www.linux-bg.org/cgi-bin....t=20656



Активен

Powered by Debian GNU / LINUX /// Intel inside ...

„Насилието е последното убежище на некомпетентността“ - Айзък Азимов (1920 — 1992)

VladSun

  • Moderator
  • Участник
  • *****
  • Публикации: 2166
    • Профил
Задача 2 - 10.09 - 16.09 - quotes web service
« Отговор #9 -: Сеп 12, 2007, 02:53 »
Цитат (the_real_maniac @ Сеп. 11 2007,21:36)
Цитат на: VladSun,Сеп. 11 2007,18:01
FIRST!

offtopic:

Примерен код

F U C K !


 '<img'>  '<img'>  '<img'>  '<img'>  ':p'  'B)'  '<img'>  '<img'>

http://www.linux-bg.org/cgi-bin....t=20656хахаххахаха - първият досетил се - имаш една бира от мен '<img'>



Активен

KISS Principle ( Keep-It-Short-and-Simple )
http://openfmi.net/projects/flattc/
Има 10 вида хора на този свят - разбиращи двоичния код и тези, които не го разбират :P

cvludmiloff

  • Участник
  • *****
  • Публикации: 54
    • Профил
Задача 2 - 10.09 - 16.09 - quotes web service
« Отговор #10 -: Сеп 12, 2007, 11:28 »
quotes.py

Примерен код

import BaseHTTPServer
import sys
import re
import random

class SimpleDispatchHandler(BaseHTTPServer.BaseHTTPRequestHandler):
    cleanse_re = re.compile('\W')

    # -----------------------------------------------

    def do_GET(self):
        """
        The main dispatcher.
        Assumes the first part of the url is the method to call and the subsequent parts are parameters for the method.
        For example, "http://localhost:8000/test/a/b/c"
        would invoke self.method_test() passing it the list ['a', 'b', 'c']
        """
        path = self.path.split('/')
        method = path[1]
        method = self.cleanse_re.sub('',method)
        method_imp = None

        try:
            method_impl = getattr(self, "method_"+method)
        except Exception, e:
            self.send_error( 404 )
            self.wfile.write( "<br/ ><b>Method unknown [" + method + "]</b>\n" )
            return

        try:
            method_impl( path[2:] )
        except Exception, e:
            self.send_error( 500 )
            self.wfile.write( "<br/ ><b>Error in method [" + method + "]: " + str(e) + "</b>\n" )

        return

    # -----------------------------------------------

    def html( self ):
        """
        Sends the appropriate headers to indicate html output
        """
        self.send_response(200)
        self.send_header("Content-type", "text/html")
        self.end_headers()

    def fortunes(self, infile):
        """ Yield fortunes as lists of lines """
        result = []
        for line in infile:
            if line == "%\n":
                yield result
                result = []
            else:
                result.append(line)
        if result:
            yield result

    def findfortune(self, filename):
        """ Pick a random fortune from a file """
        for index, fortune in enumerate(self.fortunes(file(filename))):
            if random.random() < (1.0 / (index+1)):
                chosen = fortune

        return "".join(chosen)

    # -----------------------------------------------

    def method_fortune( self, params ):
        """
        Test method, included only to show how custom methods would be created.
        """
        self.html()
        if len(params) == 0:
            params = ['/usr/share/games/fortunes/fortunes',]
        text = self.findfortune(params[0])
        self.wfile.write(text)
        self.wfile.write( "<br /><br />Here are the parameters: " + str(params) + "<br />")

PORT = 8000
httpd = BaseHTTPServer.HTTPServer(("", PORT), SimpleDispatchHandler)
print "serving at port", PORT
httpd.serve_forever()    


стартира се:
python quotes.py

от браузер: http://localhost:8000/fortune



Активен

zeridon

  • Killmode enabled
  • Administrator
  • Участник
  • *****
  • Публикации: 1398
  • Distribution: Debian/Ubuntu
  • Window Manager: console/Gnome
  • BOfH
    • Профил
    • WWW
Задача 2 - 10.09 - 16.09 - quotes web service
« Отговор #11 -: Сеп 15, 2007, 10:22 »
VladSun бих препоръчал изхода да се загради в някакви разделители (от гледна точка на по добро парсене от външен софт)

Иначе до момента всичките предложения ми изглеждат читави '<img'>
Активен

Внмимавай имам клещи за кабел
http://www.netsecad.com/
http://theregister.co.uk/odds/bofh/

paranoid

  • Участник
  • *****
  • Публикации: 67
    • Профил
Задача 2 - 10.09 - 16.09 - quotes web service
« Отговор #12 -: Сеп 15, 2007, 13:59 »
Според мен, условието не е зададено правилно, защото доколкото знам уеб-сървисите работят на основата на SOAP протокола, а доколкото видях нищо такова не се казваше в условието. Освен това къде е изискването за WSDL?
Активен

VladSun

  • Moderator
  • Участник
  • *****
  • Публикации: 2166
    • Профил
Задача 2 - 10.09 - 16.09 - quotes web service
« Отговор #13 -: Сеп 15, 2007, 14:50 »
@zeridon - по-скоро трябва да си оправя изхода в контекста на content-type-a, ама реших, че това трябва да е проблем на `fortune` '<img'>  ':p'
Активен

KISS Principle ( Keep-It-Short-and-Simple )
http://openfmi.net/projects/flattc/
Има 10 вида хора на този свят - разбиращи двоичния код и тези, които не го разбират :P

task_struct

  • Участник
  • *****
  • Публикации: 576
  • Distribution: Kubuntu 14.04
  • Window Manager: KDE 4.13
    • Профил
Задача 2 - 10.09 - 16.09 - quotes web service
« Отговор #14 -: Сеп 16, 2007, 10:17 »
Ето и моя вариант:
Примерен код

#include <stdio.h>
#include <stdlib.h>
#include <stdarg.h>
#include <string.h>
#include <unistd.h>
#include <signal.h>
#include <sys/param.h>
#include <sys/socket.h>
#include <sys/stat.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <netdb.h>
#include <fcntl.h>
#include <errno.h>
#include <time.h>
#include <pwd.h>

#define _GNU_SOURCE
#include <getopt.h>

#define DEFAULT_PORT 1987
#define DEFAULT_USER "nikolay"
#define LOGFILE "/home/nikolay/access_log"
#define BACKLOG 5

int sockfd, sockfd_new; /* дескриптори на гнезда */

void sisd_log(char *fmt, ...)
{
     va_list args;
     char buffer[128];
     FILE *logfd;

     if((logfd = fopen(LOGFILE, "a")) == 0) {
          fclose(logfd);
          exit(1);
     }

     va_start(args, fmt);
     vsprintf(buffer, fmt, args);
     va_end(args);

     fprintf(logfd, buffer);

     fclose(logfd);

}

void p_error(char error[], int errnum, int how)
{
     sisd_log("%s error #%d\n", errno, errnum);

     if(how == 0)
          exit(2);
     if(how == 1) {
          close(sockfd);
          exit(3);
     }
     if(how == 2) return;
     if(how == 3) {
          shutdown(sockfd_new, 2);
          close(sockfd_new);
          return;
     }
     if(how == 4) {
          shutdown(sockfd_new, 2);
          close(sockfd_new);
          usleep(100);
          exit(4);
     }
}

void process(FILE *f, char *cl)
{
     time_t now;
     char timebuf[128];

     fprintf(f, "HTTP/1.1 200 OK\r\n");
     fprintf(f, "Server: SIS\r\n");
     now = time(NULL);
     strftime(timebuf, sizeof(timebuf), "%a, %d %b %Y %H:%M:%S GMT", gmtime(&now));
     fprintf(f, "Date: %s\r\n", timebuf);
     fprintf(f, "Content-Type: text/html\r\n");
     fprintf(f, "Connection: close\r\n");
     fprintf(f, "\r\n");
     fprintf(f, "<html><head><title>SISD</title></head><body>");

     FILE *read_fp;
     char buf[BUFSIZ];

     memset(buf, '\0', sizeof(buf));
     read_fp = popen("fortune", "r");
     if(read_fp != NULL) {
          fread(buf, sizeof(buf), 1, read_fp);
          pclose(read_fp);
          fprintf(f, buf);
     }
     else {
          fprintf(f, "Error!");
     }
     memset(buf, '\0', sizeof(buf));

     fprintf(f, "</body></html>");

     sisd_log("Connection from %s at %s\n", cl, timebuf);
}

int main(int argc, char *argv[])
{
     int opt;
     int port = -1;
     char user[21] = "\n", logfile[256] = "\n";
     struct option opts[] = {
          {"port", 2, NULL, 'p'},
          {"username", 2, NULL, 'u'},
          {"logfile", 2, NULL, 'l'},
          {"version", 0, NULL, 'v'},
          {"help", 0, NULL, 'h'}};

     /*************************************************/
     /* обработване на входните параметри */
     /************************************************/
     while((opt = getopt_long(argc, argv, "p:u:l:vh", opts, NULL)) != -1) {
          switch(opt) {
               case 'p': {
                    if(optarg) {
                         port = (int)optarg;
                    }
                    else {
                         port = DEFAULT_PORT;
                    }
                    break;
               }
               case 'u': {
                    if(optarg) {
                         strncpy(user, optarg, 20);
                    }
                    else {
                         strcpy(user, DEFAULT_USER);
                    }
                    break;
               }
               case 'l': {
                    if(optarg) {
                         strncpy(logfile, optarg, 255);
                    }
                    else {
                         strcpy(logfile, LOGFILE);
                    }
                    break;
               }
               case 'v': {
                    printf("Simple Info Server deamon (SISD) 1.0\n");
                    return 0;
               }
               case 'h': {
                    printf("Simple Info Server deamon (SISD) 1.0\n");
                    printf("Server provides system information in text/html format.\n");
                    printf("Nikolay Stefanov 2007\n");
                    return 1;
               }
               case ':': {
                    printf("Option %s needs a value\n", optarg);
                    return 1;
               }
               case '?': {
                    printf("Unknown option: %c\n", optopt);
                    return 2;
               }
          }
     }

     /* ако не са зададени опции p,u,l */
     if(port == -1) {
          port = DEFAULT_PORT;
     }

     if(strcmp(user, "\n") == 0) {
          strcpy(user, DEFAULT_USER);
     }

     if(strcmp(logfile, "\n") == 0) {
          strcpy(logfile, LOGFILE);
     }

     /****************************************************************/
     /* Настройване на сървъра за работа като deamon */
     /***************************************************************/
     struct passwd *usr = getpwnam(user);

     printf("Starting deamon as %s(%d:%d) at port: %d ...\n", user, usr->pw_uid, usr->pw_gid, htons(port));
     /* затварят се всички отворени файлове */
     int i;
     for(i=0; i<NOFILE; i++)
          close(i);
     /* стартира се нова сесия */
     switch(fork()) {
          case -1: p_error("First fork()", errno, 0);
          default: exit(0);
          case 0: { /* първо дете стартира нова сесия */
               if(setsid() == -1) /* детето става лидер на новата сесия */
                    p_error("setsid()", errno, 0);
               if(setuid(usr->pw_uid) == -1)
                    p_error("setuid()", errno, 0);
               if(setgid(usr->pw_gid) == -1)
                    p_error("setgid()", errno, 0);
               switch(fork()) { /* второ пораждане на дете */
                    case -1: p_error("Second fork()", errno, 0);
                    case 0: umask(0); break; /* второто дете не е лидер на сесия */
                    default: exit(0); /* завършва втория родител (първо дете) */
               }
          }
     }

     sigset(SIGCHLD, SIG_IGN); /* сигнала се игнорира за да няма зомбита */

     /* създава се потоково гнездо */
     if((sockfd = socket(AF_INET, SOCK_STREAM, 0)) == -1)
          p_error("Could not create socket", errno, 0);

     struct sockaddr_in addr, client_addr;
     socklen_t addrlen;
     int flags;

     memset(&addr, 0, sizeof(addr));
     memset(&client_addr, 0, sizeof(client_addr));

     addr.sin_family = AF_INET;
     addr.sin_port = htons(port);
     addr.sin_addr.s_addr = INADDR_ANY;

     /* присвоява се адрес на гнездото */
     if(bind(sockfd, (struct sockaddr *)&addr, sizeof(addr)) == -1)
          p_error("bind()", errno, 1);

     /* подготовка на гнездото за приемане на заявки */
     if(listen(sockfd, BACKLOG) == -1)
          p_error("listen()", errno, 1);
     if((flags = fcntl(sockfd, F_GETFL)) == -1 || fcntl(sockfd, F_SETFL, flags & ~O_NONBLOCK) == -1) /* блокира до пристигане на заявката */
          p_error("fcntl()", errno, 1);

     /* получаване и обслужване на клиентски заявки */
     for(;;) {
          addrlen = sizeof(client_addr);
          
          /* ново гнездо и установяване на връзка с гнездо на клиент */
          if((sockfd_new = accept(sockfd, (struct sockaddr*)&client_addr, &addrlen)) < 0) {
               p_error("accept()", errno, 2); continue;
          }
          switch(fork()) {
               case -1: p_error("fork() client", errno, 2); continue;
               case 0: {
                    FILE *f;
                    if(!(f = fdopen(sockfd_new, "r+"))) {
                         p_error("fdopen", errno, 2); continue;
                    }
                    process(f, inet_ntoa(client_addr.sin_addr));
                    fclose(f);

                    shutdown(sockfd_new, 2); /* закрива се връзката */
                    close(sockfd_new); /* новото гнездо се унищожава */
                    sleep(1); /* дава шанс на клиента да завърши успешно */
                    exit(0); /* детето завършва */
               }
          }
          close(sockfd_new); /* родител - затваря новия дескриптор */
     }
     return 0;
}


Има някой бъгчета, но това ми е първата програма със сокети която пиша '<img'>

P.S. Мисля да напиша и един сървър на С#. Най-вероятно няма да успея да спазя срока, но да има пример и за такъв. Може пък на някой някога да му потрябва пример как НЕ се прави  ':p'  '<img'>



Активен

"Minds are like parachutes. They only function when they are open." - James Dewar

irc.freenode.net  / #linux-bg

Подобни теми
Заглавие Започната от Отговора Прегледи Последна публикация
Kak da napravq skript service?
Настройка на програми
karolev 1 6675 Последна публикация Ное 27, 2002, 14:17
от brady
Проблем със Qmail service
Настройка на програми
Shoty 9 7635 Последна публикация Окт 21, 2005, 12:23
от PlamenB
PPPoE Service Name в UBUNTU
Настройка на програми
moosehead 0 4094 Последна публикация Фев 22, 2006, 02:16
от moosehead
Customer service representative with French
Търсене
AdeccoBulgaria 0 3263 Последна публикация Сеп 29, 2009, 16:51
от AdeccoBulgaria
minimal service on startup
Настройка на програми
vox 11 7532 Последна публикация Сеп 12, 2011, 10:20
от plamen_f