最近在试验 oauth 认证的功能,中间涉及多个 http 请求过程,由于不清楚两者参数的对应关系,导致耽误了一些时间,这里简单记录两者参数的对应关系,以备查询。
在开发过程中,为了先熟悉请求交互的过程,一般先是通过 postman 来拼接参数模拟 http 请求, 在 postman 上能够得到正确结果了才会考虑具体写代码实现 http 请求。
下图是 postman 的请求窗口截图,针对我们需要关注的点列出了编号。
1. 方法
常用的就是 GET 和 POST 两种。
在 curl 中,如果没有设置请求的方法,默认是 GET 方法,设置 POST 请求的方法如下:
curl_easy_setopt(m_curl, CURLOPT_POST, 1);
2. url
这里输入我们执行请求的 http 地址。
在 curl 中,设置请求地址的方法如下:
curl_easy_setopt(m_curl, CURLOPT_URL, url.c_str());
3.Params
通过 Params 设置的参数,会拼接在 http 的 url 后面,例如:
在 curl 中设置 Params 参数的方式如下:
std::map params;
std::string ret;
for (auto & iter : params) {
ret.append(iter.first);
ret.append("=");
ret.append(iter.second);
ret.append("&");
}
ret.pop_back();
curl_easy_setopt(m_curl, CURLOPT_POSTFIELDS, ret.c_str());
curl_easy_setopt(m_curl, CURLOPT_POSTFIELDSIZE, ret.length());
4.Authorization
这里生成认证的键值对,我们只需要在 Authorization 下输入用户名和密码,点击右侧的 橙色按钮“Update Request” 就会自动生成一个键值对添加到 Headers 中。
生成认证的键值对的过程,在 curl 的实现如下:
std::string input_str(m_username);
input_str.append(":");
input_str.append(m_password);
curl_easy_setopt(m_curl, CURLOPT_USERPWD, input_str.c_str());
curl_easy_setopt(m_curl, CURLOPT_HTTPAUTH, CURLAUTH_BASIC);
5. Headers
Headers 对应的是 http 的请求头,除了上面提到的 Authorization 外,还可以添加其他参数,如图:
在 curl 中添加请求头的方法如下:
std::map m_headers;
struct curl_slist *headers = nullptr;
for (auto & iter: m_headers) {
headers = curl_slist_append(headers, (iter.first + ":" + iter.second).c_str());
}
curl_easy_setopt(m_curl, CURLOPT_HTTPHEADER, headers);
6.Body
在 Body 中可以按照与服务器的约定传递任何字符串,只要服务器端能够解析即可。
7.Response
这里就是显示请求的返回结果。
HttpRequest.h
#pragma once
#include
HttpRequest.cpp
#include "HttpRequest.h"
HttpRequest::HttpRequest() {
curl_global_init(CURL_GLOBAL_DEFAULT);
}
HttpRequest::~HttpRequest() {
curl_global_cleanup();
}
void HttpRequest::SetHeaders(const std::map& headers) {
m_headers = headers;
}
void HttpRequest::SetHeaders(const std::string& key, const std::string& value) {
m_headers.insert(std::make_pair(key, value));
}
void HttpRequest::SetParams(const std::map& params) {
m_params = params;
}
void HttpRequest::SetParams(const std::string& key, const std::string& value) {
m_params.insert(std::make_pair(key, value));
}
HttpResponse HttpRequest::HttpGet(const std::string & url) {
return HttpResponse();
}
HttpResponse HttpRequest::HttpPost(const std::string & url) {
m_curl = curl_easy_init();
if (!m_curl) {
std::cerr<< "m_curl is nullptr.";
return HttpResponse();
}
HttpResponse response;
curl_easy_setopt(m_curl, CURLOPT_POST, 1);
curl_easy_setopt(m_curl, CURLOPT_URL, url.c_str());
curl_easy_setopt(m_curl, CURLOPT_SSL_VERIFYPEER, true);
curl_easy_setopt(m_curl, CURLOPT_SSL_VERIFYHOST, true);
curl_easy_setopt(m_curl, CURLOPT_READFUNCTION, nullptr);
curl_easy_setopt(m_curl, CURLOPT_WRITEFUNCTION, ResponseCallback);
curl_easy_setopt(m_curl, CURLOPT_WRITEDATA, (void *)(&(response.m_responseBody)));
curl_easy_setopt(m_curl, CURLOPT_NOSIGNAL, 1);
curl_easy_setopt(m_curl, CURLOPT_HEADER, 1);
curl_easy_setopt(m_curl, CURLOPT_CONNECTTIMEOUT, 5); // set transport and time out tim
curl_easy_setopt(m_curl, CURLOPT_TIMEOUT, 10);
std::string post_fieleds = MapToStr(m_params);
if (!post_fieleds.empty()) {
curl_easy_setopt(m_curl, CURLOPT_POSTFIELDS, post_fieleds.c_str());
curl_easy_setopt(m_curl, CURLOPT_POSTFIELDSIZE, post_fieleds.length());
}
if (m_basicAuthRequired) {
std::string input_str(m_username);
input_str.append(":");
input_str.append(m_password);
curl_easy_setopt(m_curl, CURLOPT_USERPWD, input_str.c_str());
curl_easy_setopt(m_curl, CURLOPT_HTTPAUTH, CURLAUTH_BASIC);
}
if (!m_headers.empty()) {
struct curl_slist *headers = nullptr;
for (auto & iter: m_headers) {
headers = curl_slist_append(headers, (iter.first + ":" + iter.second).c_str());
}
curl_easy_setopt(m_curl, CURLOPT_HTTPHEADER, headers);
}
CURLcode ret = curl_easy_perform(m_curl);
if (ret == CURLE_OK) {
long reponseCode = 0;
ret = curl_easy_getinfo(m_curl, CURLINFO_RESPONSE_CODE, &reponseCode);
response.m_responseCode = reponseCode;
}
else {
std::cerr << "curl_easy_perform failed: " << ret;
}
Clean();
return response;
}
size_t HttpRequest::ResponseCallback(char* buffer, size_t size, size_t count, std::string* response) {
if (!buffer || !response)
{
return 0;
}
response->append(buffer);
return size * count;
}
std::string HttpRequest::MapToStr(const std::map& params) {
if (params.empty()) {
return "";
}
std::string ret;
for (auto & iter : params) {
ret.append(iter.first);
ret.append("=");
ret.append(iter.second);
ret.append("&");
}
ret.pop_back();
return ret;
}
void HttpRequest::SetHttpAuth(const std::string& username, const std::string& password) {
m_username = username;
m_password = password;
}
void HttpRequest::SetBasicAuth(bool basicAuth) {
m_basicAuthRequired = basicAuth;
}
void HttpRequest::Clean() {
curl_easy_cleanup(m_curl);
m_headers.clear();
m_params.clear();
m_username.clear();
m_password.clear();
m_basicAuthRequired = false;
}
postman 是一款很好用工具, curl 是非常强大的网络库,两者结合使用能给我们网络开发带来很大的便利,目前先了解到这个地步,以后需要用到再进一步学习吧!