http.h

来自「Shorthand是一个强大的脚本语言」· C头文件 代码 · 共 359 行

H
359
字号
#ifndef __http_h
#define __http_h
/////////////////////////////////////////////////////////////////////////////
// $Header: /shorthand/src/http.h 4     8/28/02 6:27a Arm $
//---------------------------------------------------------------------------
// This file is part of "libAndrix" library - a collection of classes
// and functions developed by Andrei Remenchuk.
//---------------------------------------------------------------------------
// While you may own complete copyright on the project with which you have
// received this file, the author reserves the right to use code contained
// in this very file for any purposes, including publishing and usage in
// any free or commercial software.
//
// You may re-distribute this file or re-use it in your own free or
// commercial software provided that this text is included in the file.
// If you change this file you must include clear notice stating that
// you changed this file and the date of change.
//
// This statement doesn't apply to other files that are part of the same
// package unless otherwise noted.
//---------------------------------------------------------------------------
// (c) 1998-2002 Andrei Remenchuk <andrei@remenchuk.com>
//---------------------------------------------------------------------------
// http.h - HTTP client
/////////////////////////////////////////////////////////////////////////////

#include <stdio.h>

#include "map.h"
#include "cstring.h"
#include "datetime.h"


/**
 * Generic URL object.
 */
class CURL
{
protected:
    string m_url;
    string m_host;
    string m_port;
    string m_protocol;

    /** uri: everything that follows host name (or '/' if nothing follows) */
    string m_uri;
    
    /** path: everything from host (with '/' at the beginning up to first '?' */
    string m_path;
    
    /** directory: everything starting from '/' until last slash or '?' */
    string m_directory;
    
    /** file: everything after last slash until end-of-line or '?' */
    string m_file;
    
    /** query: everything after ? (or empty if there is no '?') */
    string m_query;

    /** top-level domain name (com/org/uk, etc.) */
    string m_tld;

private:
    void ctor();


public:
    
    CURL();
    CURL(const char* spec);
    CURL(const CURL& curl);
    
    void clear();

    /** Parses URL from string specification. All member variables are replaced. */
    void parse(const char* spec);

    /** Makes deep copy of another URL object. */
    void copyfrom(const CURL& curl);

    /** Returns complete URL as string */
    const char* url() const { return m_url; }

    /** Returns hostname part of the URL as string */
    const char* host() const { return m_host; }

    /** Returns port part of the URL as string (which is empty if not explicitly defined) */
    const char* port() const { return m_port; }

    /** Returns protocol part of the URL as string (which is empty if not explicitly defined) */
    const char* protocol() const { return m_protocol; }

    /** Returns URI part of the URL as string (which is "/" if not explicitly defined) */
    const char* uri() const { return m_uri; }

    const char* path() const { return m_path; }

    const char* query() const { return m_query; }

    const char* directory() const { return m_directory; }

    const char* file() const { return m_file; }

    bool has_host() const     { return !m_host.is_empty(); }
    bool has_protocol() const { return !m_protocol.is_empty(); }
    bool has_port() const     { return !m_port.is_empty(); }
    bool has_uri() const      { return !m_uri.is_empty(); }

    /** 
     * Returns top-level domain of the URL as string 
     * which is empty if host part was not fully-qualified name or if it 
     * was numeric address.
     */
    const char* tld() const { return m_tld; }

    /** Reports whether or not URL is empty (not initialized) */
    bool is_empty() const;
    
    /** Reports true if this is HTTPS URL */
    bool is_secure() const;


    /**
     * Assignment operator that makes deep copy of another URL object.
     */
    const CURL& operator = (const CURL& curl);


    /** 
     * Creates follow-up URL based on the address of this URL
     * and specified url which can be partial, in which case it is treated
     * as relative to the address of this response object.
     * For example, if this URL is from "https://www.my-server.com:3833/",
     * and given url is /login.html?, the following URL will be produced:
     * "https://www.myserver.com:3833/login.html".
     *
     * @param url URL or URI relative to this document.
     * @param new_url resulting URL is written to this object.
     */
    void followup(const char* url, CURL& new_url) const;


friend class CHttpRequest;
friend class CHttpResponse;
friend class CHttpUserAgent;
};


/**
 * HTTP Cookie
 */
/**
 * HTTP Cookie object.
 */
class CHttpCookie
{
protected:
    string m_name;
    string m_value;
    datetime m_expires;
    bool   m_expireable;

    string m_path;
    string m_domain;
    bool   m_secure;
    
    bool   m_deleted;

protected:
    
    CHttpCookie();
    void ctor();

public:
    /**
     * Constructs cookie based on external spec, which is the format used
     * in Set-Cookie: response header)
     */
    CHttpCookie(const char* spec);

    CHttpCookie(const char* name, const char* value, const datetime& expires, const char* path, const char* domain, bool secure);

    /** Clones this cookie (makes new deep copy) */
    CHttpCookie* clone() const;
    
    /** Deep-copies all member fields from another cookie */
    void copyfrom(const CHttpCookie& cookie);     

    /** Returns cookie name (always defined) */
    const char* name() const { return m_name; }

    /** Returns cookie value (empty string if not defined) */
    const char* value() const { return m_value; }

    /** Returns cookie domain  (empty string if not defined) */
    const char* domain() const { return m_domain; }

    /** Returns cookie path (empty string if not defined */
    const char* path() const { return m_path; }

    /** Reports whether or not the cookie is "secure" */
    bool is_secure() const { return m_secure; }

    /** Returns expiration date (date is "empty" date if cookie is not persistent) */
    const datetime& expires() const { return m_expires; }

    /** Changes the name of the cookie */
    void set_name(const char* name) { m_name = name; }

    /** Changes the value of the cookie (NULL is treated as empty string) */
    void set_value(const char* value) { m_value = value; }

    /** Changes cookie domain (NULL ok) */
    void set_domain(const char* domain) { m_domain = domain; }

    /** Changes cookie path (NULL ok) */
    void set_path(const char* path) { m_path = path; }

    /**
     * Changes expiration date of the cookie. Also changes "expireable" flag
     * depending on whether the date is empty/invalid or not.
     */
    void set_expiration(const datetime& d)
    {
        m_expires = d;
        m_expireable = d.is_valid();
    }

    void set_secure(bool secure) { m_secure = secure; }

    /**
     * Reports whether or not the cookie is "expireable". The cookie is expireable
     * if expiration date for it has been explicitly set.
     * If this is not the case (no expiration date), cookie is considered to be not persistent.
     */
    bool is_expireable() const { return m_expireable; }

    /** Parses cookie from external spec */
    bool parse(const char* spec);
    
    /** reports whether or not this cookie's domain and path
     *  matches specified URL */
    bool matches(const CURL& url);

    /** Reports whether or not the cookie is expired at the current moment */
    bool is_expired();

    /** Reports whether or not this cookie was deleted (mark_for_deletion() method was called) */
    bool is_deleted() { return m_deleted; }

    /** Marks cookie as logically "deleted" */
    void mark_for_deletion() { m_deleted = true; }

    void create_response(string& s, bool omit_header_name = false);

//friend class CHttpUserAgent;
friend class CHttpCookieJar;
//friend class CHttpResponse;
};


/**
 * Cookie Jar
 */
class CHttpCookieJar : public array<CHttpCookie>
{
public:
    CHttpCookieJar();
    CHttpCookie* find(const char* name, const char* domain);
};


/**
 * Generic HTTP stream handler interface. 
 * Depending on the way the program is invoked, different implementations 
 * will provide different output methods.
 */
class HttpStream
{
public:
    // reads from HTTP request (this must yield POSTed data if any)
    // returns number of bytes read.
    virtual int http_read(void* buffer, int buffer_size) = 0;

    // tries to find INBOUND cookie (received in request from client).
    // returned cookie object (if any) should be located in internal storage.
    // the caller must clone the cookie if it wishes to use it afterwards
    virtual const char* http_get_cookie(const char* name) = 0;

    // sets http cookie to be sent to the client (outbound cookie)
    virtual int http_set_cookie(const CHttpCookie* cookie) = 0;

    // adds header to the list of headers 
    virtual int http_add_header(const char* name, const char* value) = 0;

    // reports whether or not the headers have been already sent
    virtual bool http_headers_sent() = 0;

    // overrides HTTP response code (with optional status line message)
    // most servers will allow to change code, but few allow to change message
    virtual void http_set_response_code(int code, const char* msg) = 0;

    // writes a chunk of data to the HTTP stream
    virtual int http_write_chunk(const void* chunk_data, unsigned int chunk_length) = 0;
    
    // flushes any buffered data down the stream and sends implementation-defined 
    // indication that document output is finished. 
    // this method must also send headers if they were not sent before
    virtual int http_finalize() = 0;
};

/**
 * Implementation of standard input/output HTTP stream.
 * This implementation is used when the program works in CGI script mode.
 */
class StandardHttpStream : public HttpStream
{
private:
    map<string*> m_headers;
    
    // inbound cookies
    map<string*> m_in_cookies;

    // outbound cookies
    CHttpCookieJar m_out_cookies;

    bool m_cookies_grabbed;
    bool m_headers_sent;
    int  http_send_headers();
    int  m_status;
    string m_status_msg;

    void grab_cookies();

public:
    
    StandardHttpStream();

    // tries to find INBOUND cookie (received in request from client).
    // returned cookie object (if any) should be located in internal storage.
    // the caller must clone the cookie if it wishes to use it afterwards
    const char* http_get_cookie(const char* name);
    
    int  http_read(void* buffer, int size);
    bool http_headers_sent();
    int  http_add_header(const char* name, const char* value);
    int  http_write_chunk(const void* chunk_data, unsigned int chunk_length);
    int  http_finalize();
    void http_set_response_code(int code, const char* msg);
    
    // sets http cookie to be sent to the client
    int http_set_cookie(const CHttpCookie* cookie);
};


#endif //__chunk_h


⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?