2021SC@SDUSC BRPC源码分析(九)HTTP

本文深入探讨了HTTP2 URI类的实现,包括如何设置、获取和修改URL的不同组成部分,如scheme、host、port、path、query等。同时介绍了HttpHeader类,用于处理HTTP消息的版本、内容类型、头信息和状态码等。源码分析涵盖了URI的查询映射操作,如添加、删除查询参数,并提供了高效的方法来处理HTTP请求和响应的头部信息。
摘要由CSDN通过智能技术生成

2021SC@SDUSC BRPC源码分析(九)HTTP2

class URI {
public:
    static const size_t QUERY_MAP_INITIAL_BUCKET = 16;
    typedef butil::FlatMap<std::string, std::string> QueryMap;
    typedef QueryMap::const_iterator QueryIterator;
    URI();
    ~URI();
 
    void Swap(URI &rhs);
    void Clear(); 
    
    int SetHttpURL(const char* url);
    int SetHttpURL(const std::string& url) { return SetHttpURL(url.c_str()); }

    void operator=(const char* url) { SetHttpURL(url); }
    void operator=(const std::string& url) { SetHttpURL(url); }

    const butil::Status& status() const { return _st; }
	const std::string& scheme() const { return _scheme; }
    BAIDU_DEPRECATED const std::string& schema() const { return scheme(); }
    const std::string& host() const { return _host; }
    int port() const { return _port; } // -1 on unset.
    const std::string& path() const { return _path; }
    const std::string& user_info() const { return _user_info; }
    const std::string& fragment() const { return _fragment; }
    const std::string& query() const;
    void GenerateH2Path(std::string* h2_path) const;
    
    void set_scheme(const std::string& scheme) { _scheme = scheme; }
    BAIDU_DEPRECATED void set_schema(const std::string& s) { set_scheme(s); }
    void set_path(const std::string& path) { _path = path; }
    void set_host(const std::string& host) { _host = host; }
    void set_port(int port) { _port = port; }
    void SetHostAndPort(const std::string& host_and_optional_port);

    void SetH2Path(const char* h2_path);
    void SetH2Path(const std::string& path) { SetH2Path(path.c_str()); }

    const std::string* GetQuery(const char* key) const
    { return get_query_map().seek(key); }
    const std::string* GetQuery(const std::string& key) const
    { return get_query_map().seek(key); }

    void SetQuery(const std::string& key, const std::string& value);   

    size_t RemoveQuery(const char* key);
    size_t RemoveQuery(const std::string& key);

    QueryIterator QueryBegin() const { return get_query_map().begin(); }
    QueryIterator QueryEnd() const { return get_query_map().end(); }
    
    void PrintWithoutHost(std::ostream& os) const;
    void Print(std::ostream& os) const;

private:
friend class HttpMessage;

    void InitializeQueryMap() const;

    QueryMap& get_query_map() const {
        if (!_initialized_query_map) {
            InitializeQueryMap();
        }
        return _query_map;
    }

    void AppendQueryString(std::string* query, bool append_question_mark) const;
	……
	略
	……
};


int ParseURL(const char* url, std::string* scheme, std::string* host, int* port);

inline void URI::SetQuery(const std::string& key, const std::string& value) {
    get_query_map()[key] = value;
    _query_was_modified = true;
}

inline size_t URI::RemoveQuery(const char* key) {
    if (get_query_map().erase(key)) {
        _query_was_modified = true;
        return 1;
    }
    return 0;
}

inline size_t URI::RemoveQuery(const std::string& key) {
    if (get_query_map().erase(key)) {
        _query_was_modified = true;
        return 1;
    }
    return 0;
}

inline const std::string& URI::query() const {
    if (_initialized_query_map && _query_was_modified) {
        _query_was_modified = false;
        _query.clear();
        AppendQueryString(&_query, false);
    }
    return _query;
}

inline std::ostream& operator<<(std::ostream& os, const URI& uri) {
    uri.Print(os);
    return os;
}

class QuerySplitter : public butil::KeyValuePairsSplitter {
public:
    inline QuerySplitter(const char* str_begin, const char* str_end)
        : KeyValuePairsSplitter(str_begin, str_end, '&', '=')
    {}

    inline QuerySplitter(const char* str_begin)
        : KeyValuePairsSplitter(str_begin, '&', '=')
    {}

    inline QuerySplitter(const butil::StringPiece &sp)
        : KeyValuePairsSplitter(sp, '&', '=')
    {}
};

class QueryRemover {
public:
    QueryRemover(const std::string* str);
	……
	略
	……

private:
	……
	略
	……
};

void append_query(std::string *query_string,
                  const butil::StringPiece& key,
                  const butil::StringPiece& value);

}
  • Swap(URI &rhs)使用另一个URI交换内部字段。
  • Clear()重置内部字段,使得它们恢复成默认构造一样。
  • SetHttpURL()分解url并设置为相应的字段,允许并跳过标题和结尾空格。成功返回0,否则返回-1并设置status()。
  • status()返回之前的SetHttpURLprereator的状态。
  • scheme()、host()、port()、 path() 、user_info()子字段。如果没有设置该字段,则为空字符串。
  • query()这个方法线程不是安全的,因为如果成功调SetQuery()/RemoveQuery(),它可能会重新生成查询字符串。
  • set_scheme(const std::string& scheme)、set_schema(const std::string& s)、set_path(const std::string& path)、set_host(const std::string& host)、 set_port(int port) 、SetHostAndPort(const std::string& host_and_optional_port);覆盖部分URL。(输入必须保证有效。)
  • SetH2Path设置path/query/fragment的输入形式为"path?query#fragment"
  • GetQuery()获取大小写敏感键值。返回指向该值的指针,当key不存在时返回NULL。
  • SetQuery()key或者值对现有值进行覆盖。
  • RemoveQuery()删除与’ key’相关的值。删除返回1,否则返回0。
  • QueryBegin()获取在调用SetQuery()或SetHttpURL()后失效的查询迭代器。
  • PrintWithoutHost()、Print()打印当前这个URI到ostream。PrintWithoutHost只打印包含path和after的组件。
  • AppendQueryString()迭代_query_map并附加所有查询到’ query’
  • ParseURL()从’ url’解析host/port/scheme。成功返回0,否则返回-1。
  • KeyValuePairsSplitter {}分割查询的格式为"key1=value1&key2&key3=value3"
  • remove_current_key_and_value()调用此函数后,当前查询将从modified_query()中删除,多次调用此函数无效。
  • modified_query()返回修改后的查询字符串
  • QueryRemover {}删除查询字符串中某些特定键的类,当删除结束时,调用modified_query()来获取修改后的查询。
  • append_query()考虑到query_string的所有可能格式,该函数可以向query_string追加key和值。例如:
 " -> "key=value"
 "key1=value1" -> "key1=value1&key=value"
 "/some/path?" -> "/some/path?key=value"
 "/some/path?key1=value1" -> "/some/path?key1=value1&key=value"

class HttpHeader {
public:
	……
	略
	……

    HttpHeader();
    void Swap(HttpHeader &rhs);
    void Clear();
    int major_version() const { return _version.first; }
    int minor_version() const { return _version.second; }
    void set_version(int http_major, int http_minor)
    { _version = std::make_pair(http_major, http_minor); }

    bool before_http_1_1() const
    { return (major_version() * 10000 +  minor_version()) <= 10000; }

    bool is_http2() const { return major_version() == 2; }

    const std::string& content_type() const { return _content_type; }
    void set_content_type(const std::string& type) { _content_type = type; }
    void set_content_type(const char* type) { _content_type = type; }
    std::string& mutable_content_type() { return _content_type; }
       
    const std::string* GetHeader(const char* key) const
    { return _headers.seek(key); }
    const std::string* GetHeader(const std::string& key) const
    { return _headers.seek(key); }

    void SetHeader(const std::string& key, const std::string& value)
    { GetOrAddHeader(key) = value; }
	……
	略
	……
    
    void AppendHeader(const std::string& key, const butil::StringPiece& value);
    
    HeaderIterator HeaderBegin() const { return _headers.begin(); }
    HeaderIterator HeaderEnd() const { return _headers.end(); }
    size_t HeaderCount() const { return _headers.size(); }

    const URI& uri() const { return _uri; }
    URI& uri() { return _uri; }

    HttpMethod method() const { return _method; }
    void set_method(const HttpMethod method) { _method = method; }

    int status_code() const { return _status_code; }
    const char* reason_phrase() const;
    void set_status_code(int status_code);

    const std::string& unresolved_path() const { return _unresolved_path; }

private:
	……
	略
	……
};
const HttpHeader& DefaultHttpHeader();
}
  • Swap():与另一个HttpHeader交换内部字段。
  • Clear()重置内部字段,使得它们恢复成默认构造一样。
  • major_version()获取http版本。
  • set_version修改http版本。
  • before_http_1_1()如果http的版本低于1.1,则为True,否则为false。
  • is_http2()如果消息来自HTTP2,则为True,否则为false。
  • set_content_type/获取/设置内容类型。无法通过GetHeader()获得“Content-Type”。可能的值:“text/plain”,“application/json”……
  • GetHeader()获取不区分大小写的报头值,即GetHeader(“log-id”),GetHeader(“log-id”), GetHeader(“log-id”)·指向相同的值。返回指向该值的指针,如果未找到,返回NULL。不工作时在"Content-Type",调用content_type()代替。
  • SetHeader()设置header的值。不工作时在"Content-Type",调用set_content_type()代替。
  • AppendHeader()将值附加到头。如果头已经存在,用逗号(,)分隔旧值和新值
  • HeaderBegin()获取在调用AppendHeader()之后失效的头迭代器
  • URI& uri()获取URI对象,检查src/brpc/ URI .h获取详细信息。
  • method()、set_method()获取/设置http方法。
  • status_code() 、reason_phrase()、 set_status_code(int status_code)获取/设置状态代码和原因短语。注意,由reason_phrase()返回的const char*将在下一次调用set_status_code()之后失效。
  • unresolved_path()删除URL路径被匹配的前缀。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值