curl c api

 curl c api

关于Curl的介绍很多,这里不详细介绍,主要谈一下简单应用。
最近研究了一下Linux下的curl C API,curl c API的文档比较丰富,唯一就是查找起来,费些时间。Curl的C API和curl的PHP API,函数接口和作用大致相同,所以如果有PHP API使用经验应该很好理解。
1:CURLcode curl_global_init(long flags);函数,这个函数全局需要调用一次(多次调用也可以,不过没有必要), 所以这也是把Curlplus设计成单体类的原因,curl_global_init函数在其他libcurl函数调用前至少调用一次,程序最后需要调用curl_global_cleanup,进行清理。
参数:flags 
CURL_GLOBAL_ALL Initialize everything possible. This sets all known bits.
CURL_GLOBAL_SSL Initialize SSL
CURL_GLOBAL_WIN32 Initialize the Win32 socket libraries.
CURL_GLOBAL_NOTHING Initialise nothing extra. This sets no bit.
CURLcode 是一个enum,当CURLcode为CURLE_OK时,表示函数执行成功,否则失败,具体错误原因可以查看<curl/curl.h>文件内的定义。
2:curl_easy_init - Start a libcurl easy session
curl_easy_init用来初始化一个CURL的指针(有些像返回FILE类型的指针一样). 相应的在调用结束时要用curl_easy_cleanup函数清理. 一般curl_easy_init意味着一个会话的开始. 它的返回值是CURL *,curl_easy_init函数是线程相关的,也就是说不能在一个线程中调用另外一个线程通过curl_easy_init创建的CURL指针。
3:CURLcode curl_easy_setopt(CURL *handle, CURLoption option, parameter); 
描述: 这个函数最重要了.几乎所有的curl 程序都要频繁的使用它.它告诉curl库.程序将有如何的行为. 比如要查看一个网页的html代码等.,要想具体了解CURL的行为,必须对CURLoption有足够的了解,具体可以参考
http://curl.haxx.se/libcurl/c/curl_easy_setopt.html
这里有两个类型不易理解CURLOPT_WRITEFUNCTION,CURLOPT_WRITEDATA
curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, Curlplus::writer);
设置一个回调函数,这个回调函数的格式是
size_t function( void *ptr, size_t size, size_t nmemb, void *stream);
ptr,返回数据的指针
size,返回数据每块的大小
nmemb,返回数据的块数(这里返回数据串的真正大小为size*nmemb)
stream,是curl_easy_setopt(curl, CURLOPT_WRITEDATA, &buffer); 中的buffer的指针。
在上面的例子中,buffer设置为一个string对象,所以,在回调函数writer中有了writerData->append(data, len); 
4:CURLcode curl_easy_perform(CURL *handle);
执行远程请求
参考资料
http://curl.haxx.se/
http://curl.haxx.se/lxr/source/docs/examples/
基于curl 的C API写了一个扩展C++ singleton类(当然curl也有C++ API),这个单体类只是对HTTP请求做了简单封装,提供post,get方法,并得到请求url内的返回值(保存到string对象中),也很容易扩展到其他协议上去。
Curlplus.h文件
#ifndef _CURLPLUS_H__
#define _CURLPLUS_H__ 
#ifndef __CURL_CURL_H
#include <curl/curl.h>
#endif
#ifndef __CURL_EASY_H
#include <curl/easy.h>
#endif
#include <memory>
#include <string> 
using namespace::std; 
namespace CP
{
    class Curlplus
    {
    public:
        static  Curlplus& get_instance();
        string post(const string& url,const string& content) const;
        string get(const string& url) const;
    protected:
        Curlplus(void);
        ~Curlplus(void);
        Curlplus(const Curlplus&);
        Curlplus& operator=(const Curlplus&);
        static int writer(char *data, size_t size, size_t nmemb,std::string *writerData);
    private:
        static auto_ptr<Curlplus> _instance;
        inline void _setCurlopt(CURL *curl,const string& url) const;
        // default timeout 300s
        static const int _defaulttimeout = 300;
        static string buffer;
        friend class auto_ptr<Curlplus>;
    };
}
#endif 
Curlpuls.cc文件 
#ifndef SPIVOT_CURLPLUS_H__
#include "Curlplus.h"
#endif 
using namespace std;
using namespace CP;
 
auto_ptr<Curlplus> Curlplus::_instance;
string Curlplus::buffer;
static char errorBuffer[CURL_ERROR_SIZE]; 
Curlplus& Curlplus::get_instance()
{
    if(_instance.get() == NULL)
    {
        _instance.reset(new Curlplus());
    } 
    return *_instance.get();
}
int Curlplus::writer(char *data, size_t size, size_t nmemb, string *writerData)
{
    if (writerData == NULL)
        return 0;
    int len = size*nmemb;
    writerData->append(data, len);
    return len;
}
Curlplus::Curlplus(void)
    CURLcode code = curl_global_init(CURL_GLOBAL_ALL);
    if(code != CURLE_OK)
    {
        cout << "curl_init failed, error code is: " << code;
    }
}
Curlplus::~Curlplus(void)
{
    curl_global_cleanup();
string Curlplus::post(const string& url, const string& content) const
{
    buffer="";
    CURL *curl = curl_easy_init();
    if(curl == NULL)
    {
        cout << "curl_easy_init failed ";
    }  
    _setCurlopt(curl,url);
    curl_easy_setopt(curl, CURLOPT_POST, 1 );
    curl_easy_setopt(curl, CURLOPT_POSTFIELDS, content.c_str());   
    CURLcode code = curl_easy_perform(curl);
    if(code != CURLE_OK)
    {
        cout << "curl_easy_perform failed: "<< code;
    }
    curl_easy_cleanup(curl);
    return buffer;
string Curlplus::get(const string& url) const
{
    buffer="";
    CURL *curl = curl_easy_init();
    if(curl == NULL)
    {
        cout << "curl_easy_init failed ";
    }  
    _setCurlopt(curl,url);
    CURLcode code = curl_easy_perform(curl); 
    if(code != CURLE_OK)
    {
        cout << "curl_easy_perform failed: "<< code;
    }
    curl_easy_cleanup(curl);
    return buffer;
}
void Curlplus::_setCurlopt(CURL *curl,const string& url) const {
    curl_easy_setopt(curl, CURLOPT_ERRORBUFFER, errorBuffer);
    curl_easy_setopt(curl, CURLOPT_HEADER, 0);
    curl_easy_setopt(curl, CURLOPT_URL, url.c_str());
    curl_easy_setopt(curl, CURLOPT_TIMEOUT, _defaulttimeout);
    //curl_easy_setopt(curl, CURLOPT_VERBOSE, true);
    curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, Curlplus::writer);
    curl_easy_setopt(curl, CURLOPT_WRITEDATA, &buffer);
}
<think>嗯,用户想用curl获取Harbor的API token。我得先回忆一下Harbor的API认证流程。Harbor从v2开始可能改用JWT token而不是原来的基于数据库的token了,对吧?所以之前的通过用户名密码获取token的API可能已经变了。 首先,用户可能需要的是通过API进行认证然后获取一个临时的访问令牌。Harbor的API文档里应该有关于如何获取token的说明。我记得现在可能用的是OAuth2的密码模式,或者类似Basic认证的方式直接获取token。 先确认一下Harbor的API版本。假设用户使用的是较新版本的Harbor,比如v2.x。这时候,用户需要使用POST请求发送用户名密码到某个特定的端点,比如/service/token。或者,可能是在/v2/的某个路径下。 然后,可能需要设置请求头,比如Authorization头,使用Basic认证,把用户名密码base64编码后的字符串放进去。或者,可能需要发送表单数据,比如grant_type=password之类的参数,这取决于Harbor的OAuth2实现方式。 举个例子,如果是通过Basic认证,curl命令可能类似于: curl -u 用户名:密码 -X POST "https://harbor地址/service/token..." 或者,可能需要POST到/oauth2/token端点,携带用户名、密码client_id等信息。比如: curl -X POST -d "grant_type=password&username=admin&password=密码" -u "client_id:client_secret" https://harbor.example.com/oauth2/token 不过这里的client_idclient_secret可能对于Harbor来说是否有默认值呢?比如Harbor的默认客户端可能是什么,或者是否需要预先创建一个OAuth客户端? 另外,用户可能需要先确认Harbor的API文档,或者查看Harbor的配置,确定正确的认证端点。或者,直接尝试使用Docker login的方式获取token,然后通过Harbor的API进行交互。 还有一种情况,用户可能想获取机器人账户的token,这时候需要在Harbor中创建机器人账户,生成token,然后用这个token进行API调用。但如果是通过API动态获取的话,可能还是需要认证流程。 另外,需要注意Harbor的API是否启用了认证,以及是否需要HTTPS。可能还需要忽略SSL证书验证,这在测试环境可以用curl的-k选项,但生产环境不建议。 可能的步骤是: 1. 使用Basic认证发送POST请求到/service/token或者/oauth2/token端点。 2. 解析返回的JSON获取token。 3. 使用该token在后续请求的Authorization头中作为Bearer token。 例如,正确的curl命令可能像这样: curl -u username:password -X POST "https://harbor.example.com/service/token?service=harbor-registry&scope=repository:repo-name:pull,push" 不过需要确认实际的端点参数是否正确。或者,Harbor的API文档可能指出需要请求的路径,比如/v2/auth端点,但可能需要更多的参数。 或者,Harbor的Docker registry API使用的是标准的Docker registry认证流程,这时候获取token的方式可能类似于: curl -u "username:password" "https://harbor.example.com/service/token?service=harbor-registry&scope=repository:项目名/镜像名:pull" 这时候返回的token是用于访问特定资源的。 如果是调用Harbor的REST API(比如管理API),可能需要不同的认证方式,比如使用Bearer token,而这个token可能需要通过POST /login获取,但Harbor的某些版本中,登录API可能返回一个session cookie,而不是token。 比如,Harbor的管理API可能需要发送POST请求到/api/v2.0/login,携带用户名密码,然后返回一个session cookie,后续请求需要携带这个cookie。这可能适用于需要管理操作的API调用,但用户可能更希望使用token认证而不是基于session的认证。 例如: curl -u "username:password" -X POST "https://harbor.example.com/api/v2.0/login" 这会返回一个Set-Cookie头,里面包含sid,后续请求需要带上这个cookie。但对于自动化脚本来说,使用token更方便,所以可能需要寻找其他方式。 这时候,可能用户需要的是Harbor的机器人账户token,或者使用API密钥的方式。机器人账户可以在Harbor的项目中创建,生成一个具有特定权限的token,然后直接使用这个token作为Basic认证的用户名(比如机器人账户名加上$符号token),或者作为Bearer token。 例如,机器人账户名为robot$test,token为abc123,则Basic认证的header可以是Authorization: Basic base64("robot$test:abc123")。 总结来说,用户的问题可能有不同的情况: 1. 获取Harbor管理API的认证token(可能需要session cookie)。 2. 获取访问Docker registry的临时token(使用OAuth2或Docker registry的认证流程)。 3. 使用机器人账户的固定token。 因此,需要明确用户的具体需求。如果用户想通过API进行管理操作,可能需要使用API登录获取session,或者使用机器人账户的token。如果是访问registry,可能需要临时token。 可能给出两种方式:一种是使用Basic认证获取registry token,另一种是使用机器人账户的token。同时提醒用户查阅Harbor的官方文档,因为不同版本可能有差异。</think>使用 `curl` 获取 Harbor API Token 的方法如下: --- ### **1. 获取 Harbor 管理 API 的认证 Token(基于 Session)** Harbor 的部分管理 API 需要通过登录接口获取 Session Cookie(如 `sid`),而非传统 Token。操作步骤如下: ```bash # 发送登录请求,保存 Cookie 到文件 curl -u "用户名:密码" -X POST "https://harbor.example.com/api/v2.0/login" \ -c cookie.txt -k # -k 忽略证书验证(测试用) # 后续 API 请求携带 Cookie(示例:列出所有项目) curl -b cookie.txt "https://harbor.example.com/api/v2.0/projects" -k ``` --- ### **2. 获取 Docker Registry 临时访问 Token** 若需访问 Harbor 的 Docker Registry API(如推送/拉取镜像),需通过 OAuth2 协议获取临时 Token: ```bash curl -u "用户名:密码" "https://harbor.example.com/service/token?service=harbor-registry&scope=repository:<项目名>/<镜像名>:pull,push" -k ``` **参数说明**: - `service=harbor-registry`: 固定服务标识。 - `scope`: 指定资源权限(如 `repository:myproject/nginx:pull,push`)。 **返回示例**: ```json {"token": "eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9..."} ``` --- ### **3. 使用机器人账户 Token(推荐自动化场景)** 在 Harbor 中创建机器人账户,生成固定 Token: 1. **创建机器人账户**:进入 Harbor 项目 → `机器人账户` → 创建账户,配置权限。 2. **获取 Token**:创建时下载的 Token 文件包含 `名称` `Token`。 **使用方式**: ```bash # 机器人账户名格式:robot$<项目名>+<账户名> ROBOT_USER="robot$myproject+testbot" ROBOT_TOKEN="your_robot_token" # 以 Basic Auth 调用 API(示例:拉取镜像列表) curl -u "${ROBOT_USER}:${ROBOT_TOKEN}" "https://harbor.example.com/v2/myproject/nginx/tags/list" -k ``` --- ### **注意事项** - **HTTPS 与证书**:生产环境务必使用 HTTPS,若使用自签名证书,可添加 `--cert` `--key` 参数指定证书。 - **版本差异**:不同 Harbor 版本 API 可能略有不同,建议参考官方文档:[Harbor API v2.0](https://goharbor.io/docs/2.6.0/api/) 根据实际需求选择合适的方式,机器人账户 Token 更适合自动化场景,而临时 Token Session 适用于短期交互。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值