使用HTTP :: Server :: Simple :: CGI,如何获取标题?

时间:2015-06-03 01:44:50

标签: perl

基本上,我的问题类似于 How do I access HTTP request headers in HTTP::Server::Simple::CGI?

答案是使用parse_headers(),但没有示例如何正确使用它。我试图使用parse_headers(),但我没有得到任何结果,它只是停在parse_headers(),就像程序被卡住一样。我无法在上面的问题上添加评论,因为我没有足够的代表这样做,所以我创建了这个新问题。

下面是我的示例代码,基本上来自CPAN的示例代码刚刚添加了parse_headers:

@interface DataObject : NSObject <NSCopying>
{
@public
    unsigned int    arrPrice[10];
}

@property (nonatomic, copy) NSString *code ;
@property (nonatomic, assign) unsigned char type ;
@property (nonatomic, assign) int digit ;
@property (nonatomic, assign) unsigned int count ;
@property (nonatomic, assign) unsigned short time ;
@property (nonatomic, assign) char season ;
@property (nonatomic, assign) int64_t amount ;
@property (nonatomic, strong) NSMutableArray *mArray ;
@property (nonatomic, assign) BOOL isOk ;

@end

@implementation DataObject

- (unsigned int)sizeOfTypeEncoding:(NSString *)typeEncoding supportOrNot:(BOOL *)support
{
    *support = YES ;
    unsigned int size = 0 ;
    if ([typeEncoding isEqualToString:@"c"] ||
        [typeEncoding isEqualToString:@"C"]) {
        size = sizeof(char) ;
    } else if ([typeEncoding isEqualToString:@"i"] ||
               [typeEncoding isEqualToString:@"I"]) {
        size = sizeof(int) ;
    } else if ([typeEncoding isEqualToString:@"s"] ||
               [typeEncoding isEqualToString:@"S"]) {
        size = sizeof(short) ;
    } else if ([typeEncoding isEqualToString:@"l"] ||
               [typeEncoding isEqualToString:@"L"]) {
        size = sizeof(long) ;
    } else if ([typeEncoding isEqualToString:@"q"] ||
               [typeEncoding isEqualToString:@"Q"]) {
        size = sizeof(long long) ;
    } else if ([typeEncoding isEqualToString:@"f"]) {
        size = sizeof(float) ;
    } else if ([typeEncoding isEqualToString:@"d"]) {
        size = sizeof(double) ;
    } else if ([typeEncoding isEqualToString:@"B"]) {
        size = sizeof(bool) ;
    } else {
        *support = NO ;
        // v is void
        // * is char *
        // @ is object
        // # is class object
        // : is method selector
        // [ is array
        // { is struct
        // ( is union
        // b is bit
        // ^ pointer to type
        // ? other
        size = 0 ;
    }
    return size ;
}

- (id)copyWithZone:(NSZone *)zone
{
    DataObject *obj = [[DataObject allocWithZone:zone] init] ;
    unsigned int uVarCount = 0 ;
    Ivar *pVarList = class_copyIvarList(self.class, &uVarCount) ;
    for (unsigned int i = 0; i < uVarCount; ++i) {
        Ivar *pVar = pVarList+i ;
        const char *name = ivar_getName(*pVar) ;
        const char *typeEncoding = ivar_getTypeEncoding(*pVar) ;
        NSString *strTypeEncoding = [NSString stringWithUTF8String:typeEncoding] ;
        NSLog(@"var name:%s, type:%s", name, typeEncoding) ;
        if ([strTypeEncoding isEqualToString:@"[10I]"]) {
            // it is arrPrice
            memcpy(obj->arrPrice, self->arrPrice, sizeof(arrPrice)) ;
            continue ;
        }
        if ([strTypeEncoding hasPrefix:@"@"]) {
            // it is a object
            id o = object_getIvar(self, *pVar) ;
            o = [o copy] ;
            object_setIvar(obj, *pVar, o) ;
        } else {
            unsigned int size = 0 ;
            BOOL support = NO ;
            size = [self sizeOfTypeEncoding:strTypeEncoding supportOrNot:&support] ;
            if (!support) {
                NSString *reason = [NSString stringWithFormat:@"don't support type encoding %@", strTypeEncoding] ;
                NSException *exception = [NSException exceptionWithName:@"UnSupportTypeException" reason:reason userInfo:nil] ;
                [exception raise] ;
            }
            ptrdiff_t offset = ivar_getOffset(*pVar) ;
            uint8_t *src = (uint8_t *)(__bridge void *)self + offset ;
            uint8_t *dst = (uint8_t *)(__bridge void *)obj + offset ;
            memcpy(dst, src, size) ;
        }
    }
    free(pVarList) ;
    return obj ;
}

@end

仅添加此部分:

#!/usr/bin/perl
{
package MyWebServer;

use HTTP::Server::Simple::CGI;
our @ISA = qw(HTTP::Server::Simple::CGI);
use Data::Dumper;

my %dispatch = (
    '/hello.cgi' => \&resp_hello,
    # ...
);

sub handle_request {
    my $self = shift;
    my $cgi  = shift;

    my $path = $cgi->path_info();
    my $handler = $dispatch{$path};

    my $header = $self->parse_headers();
    open F,qq{>>~/MyWebServer.log};
    my $dump = Data::Dumper->Dump([$header], [qw($header)]);
    print F $dump;
    close F;

    if (ref($handler) eq "CODE") {
        print "HTTP/1.0 200 OK\r\n";
        $handler->($cgi);

    } else {
        print "HTTP/1.0 404 Not found\r\n";
        print $cgi->header,
              $cgi->start_html('Not found'),
              $cgi->h1('Not found'),
              $cgi->end_html;
    }
}

sub resp_hello {
    my $cgi  = shift;   # CGI.pm object
    return if !ref $cgi;

    my $who = $cgi->param('name');

    print $cgi->header,
          $cgi->start_html("Hello"),
          $cgi->h1("Hello $who!"),
          $cgi->end_html;
}

} # end of package MyWebServer

# start the server on port 8080
my $pid = MyWebServer->new(8080)->background();
print "Use 'kill $pid' to stop server.\n";

我的目标是获取所有标题并将其转储到文件中。

1 个答案:

答案 0 :(得分:1)

添加

sub headers {
    my( $self, $headers ) = @_;
    if( $headers ){
        $self->{__last_headers} = { @$headers };
    }
    return $self->{__last_headers};
}

然后在handle_request内使用my $header = $self->headers();

FWIW,我很好奇为什么你使用HTTP :: Server :: Simple :: CGI而不是Mojolicious或Dancer,甚至HTTP :: Server :: Simple :: PSGI。 https://metacpan.org/pod/PSGI是可移植性。