mirror of
https://github.com/Orange-OpenSource/hurl.git
synced 2024-11-26 00:22:10 +03:00
Add extension function on Easy for getting certinfo.
This commit is contained in:
parent
4acb12d2bd
commit
9fb1cb7801
@ -29,7 +29,7 @@ use super::request::*;
|
||||
use super::request_spec::*;
|
||||
use super::response::*;
|
||||
use super::{Header, HttpError, Verbosity};
|
||||
use crate::http::ContextDir;
|
||||
use crate::http::{easy_ext, ContextDir};
|
||||
use crate::util::logger::Logger;
|
||||
use base64::engine::general_purpose;
|
||||
use base64::Engine;
|
||||
@ -123,6 +123,9 @@ impl Client {
|
||||
// way to get access to the outgoing headers.
|
||||
self.handle.verbose(true).unwrap();
|
||||
|
||||
// Activates the access of certificates info chain after a transfer has been executed.
|
||||
self.handle.certinfo(true).unwrap();
|
||||
|
||||
if !options.connects_to.is_empty() {
|
||||
let connects = to_list(&options.connects_to);
|
||||
self.handle.connect_to(connects).unwrap();
|
||||
@ -312,6 +315,7 @@ impl Client {
|
||||
let duration = start.elapsed();
|
||||
let length = response_body.len();
|
||||
let certificate = None;
|
||||
let _certinfo = easy_ext::get_certinfo(&self.handle)?;
|
||||
self.handle.reset();
|
||||
|
||||
let request = Request {
|
||||
|
151
packages/hurl/src/http/easy_ext.rs
Normal file
151
packages/hurl/src/http/easy_ext.rs
Normal file
@ -0,0 +1,151 @@
|
||||
/*
|
||||
* Hurl (https://hurl.dev)
|
||||
* Copyright (C) 2023 Orange
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*
|
||||
*/
|
||||
use curl::easy::Easy;
|
||||
use curl::Error;
|
||||
use curl_sys::{curl_certinfo, curl_slist};
|
||||
use std::ffi::CStr;
|
||||
use std::ptr;
|
||||
|
||||
/// Represents certificate information.
|
||||
/// `data` has format "name:content";
|
||||
pub struct CertInfo {
|
||||
pub data: Vec<String>,
|
||||
}
|
||||
|
||||
/// Returns the information of the first certificate in the certificates chain.
|
||||
pub fn get_certinfo(easy: &Easy) -> Result<Option<CertInfo>, Error> {
|
||||
unsafe {
|
||||
let mut certinfo = ptr::null_mut::<curl_certinfo>();
|
||||
let rc =
|
||||
curl_sys::curl_easy_getinfo(easy.raw(), curl_sys::CURLINFO_CERTINFO, &mut certinfo);
|
||||
if rc != curl_sys::CURLE_OK {
|
||||
return Err(Error::new(rc));
|
||||
}
|
||||
if certinfo.is_null() {
|
||||
return Ok(None);
|
||||
}
|
||||
let count = (*certinfo).num_of_certs;
|
||||
if count <= 0 {
|
||||
return Ok(None);
|
||||
}
|
||||
let slist = *((*certinfo).certinfo.offset(0));
|
||||
let data = to_list(slist);
|
||||
Ok(Some(CertInfo { data }))
|
||||
}
|
||||
}
|
||||
|
||||
/// Converts an instance of libcurl linked list [`curl_slist`] to a vec of [`String`].
|
||||
fn to_list(slist: *mut curl_slist) -> Vec<String> {
|
||||
let mut data = vec![];
|
||||
let mut cur = slist;
|
||||
loop {
|
||||
if cur.is_null() {
|
||||
break;
|
||||
}
|
||||
unsafe {
|
||||
let ret = CStr::from_ptr((*cur).data).to_bytes();
|
||||
let value = String::from_utf8_lossy(ret);
|
||||
data.push(value.to_string());
|
||||
cur = (*cur).next
|
||||
}
|
||||
}
|
||||
data
|
||||
}
|
||||
|
||||
// // Iterator based implementation more similar to curl crates List implementation.
|
||||
// // See <https://github.com/alexcrichton/curl-rust/blob/main/src/easy/list.rs>
|
||||
// pub struct CertInfo2 {
|
||||
// raw: *mut curl_certinfo,
|
||||
// }
|
||||
//
|
||||
// // An iterator over CertInfo2
|
||||
// pub struct Iter<'a> {
|
||||
// me: &'a CertInfo2,
|
||||
// cur: u32,
|
||||
// }
|
||||
//
|
||||
// pub unsafe fn from_raw(raw: *mut curl_certinfo) -> CertInfo2 {
|
||||
// CertInfo2 { raw }
|
||||
// }
|
||||
//
|
||||
// impl CertInfo2 {
|
||||
// pub fn new() -> CertInfo2 {
|
||||
// CertInfo2 {
|
||||
// raw: ptr::null_mut(),
|
||||
// }
|
||||
// }
|
||||
//
|
||||
// pub fn iter(&self) -> Iter {
|
||||
// Iter {
|
||||
// me: self,
|
||||
// cur: 0,
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
//
|
||||
// impl<'a> IntoIterator for &'a CertInfo2 {
|
||||
// type Item = *mut curl_slist;
|
||||
// type IntoIter = Iter<'a>;
|
||||
//
|
||||
// fn into_iter(self) -> Iter<'a> {
|
||||
// self.iter()
|
||||
// }
|
||||
// }
|
||||
//
|
||||
// impl<'a> Iterator for Iter<'a> {
|
||||
// type Item = *mut curl_slist;
|
||||
//
|
||||
// fn next(&mut self) -> Option<*mut curl_slist> {
|
||||
// unsafe {
|
||||
// if self.cur >= (*self.me.raw).num_of_certs as u32 {
|
||||
// return None
|
||||
// }
|
||||
// let slist = *((*self.me.raw).certinfo.offset(self.cur as isize));
|
||||
// self.cur += 1;
|
||||
// Some(slist)
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::to_list;
|
||||
use std::ffi::CString;
|
||||
use std::ptr;
|
||||
|
||||
#[test]
|
||||
fn convert_curl_slist_to_vec() {
|
||||
let mut slist = ptr::null_mut();
|
||||
|
||||
unsafe {
|
||||
for value in ["foo", "bar", "baz"] {
|
||||
let str = CString::new(value).unwrap();
|
||||
slist = curl_sys::curl_slist_append(slist, str.as_ptr());
|
||||
}
|
||||
}
|
||||
|
||||
assert_eq!(
|
||||
to_list(slist),
|
||||
vec!["foo".to_string(), "bar".to_string(), "baz".to_string()]
|
||||
);
|
||||
|
||||
unsafe {
|
||||
curl_sys::curl_slist_free_all(slist);
|
||||
}
|
||||
}
|
||||
}
|
@ -42,3 +42,16 @@ pub enum HttpError {
|
||||
},
|
||||
InvalidUrl(String),
|
||||
}
|
||||
|
||||
impl From<curl::Error> for HttpError {
|
||||
fn from(err: curl::Error) -> Self {
|
||||
let code = err.code() as i32;
|
||||
let description = err.description().to_string();
|
||||
let url = "".to_string();
|
||||
HttpError::Libcurl {
|
||||
code,
|
||||
description,
|
||||
url,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -38,6 +38,7 @@ mod context_dir;
|
||||
mod cookie;
|
||||
mod core;
|
||||
mod debug;
|
||||
mod easy_ext;
|
||||
mod error;
|
||||
mod header;
|
||||
mod mimetype;
|
||||
|
Loading…
Reference in New Issue
Block a user