1 // Copyright (C) 2024 Huawei Device Co., Ltd. 2 // Licensed under the Apache License, Version 2.0 (the "License"); 3 // you may not use this file except in compliance with the License. 4 // You may obtain a copy of the License at 5 // 6 // http://www.apache.org/licenses/LICENSE-2.0 7 // 8 // Unless required by applicable law or agreed to in writing, software 9 // distributed under the License is distributed on an "AS IS" BASIS, 10 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 11 // See the License for the specific language governing permissions and 12 // limitations under the License. 13 14 use std::collections::HashMap; 15 use std::pin::Pin; 16 17 use cxx::SharedPtr; 18 19 use crate::task::RequestTask; 20 use crate::wrapper::ffi::{GetHeaders, HttpClientResponse, HttpClientTask}; 21 22 /// http client response 23 pub struct Response<'a> { 24 inner: ResponseInner<'a>, 25 } 26 27 impl<'a> Response<'a> { 28 /// Get Response Code status(&self) -> ResponseCode29 pub fn status(&self) -> ResponseCode { 30 let response = self.inner.to_response(); 31 response.GetResponseCode().try_into().unwrap_or_default() 32 } 33 headers(&self) -> HashMap<String, String>34 pub fn headers(&self) -> HashMap<String, String> { 35 let ptr = self.inner.to_response() as *const HttpClientResponse as *mut HttpClientResponse; 36 let p = unsafe { Pin::new_unchecked(ptr.as_mut().unwrap()) }; 37 38 let mut headers = GetHeaders(p).into_iter(); 39 let mut ret = HashMap::new(); 40 loop { 41 if let Some(key) = headers.next() { 42 if let Some(value) = headers.next() { 43 ret.insert(key.to_lowercase(), value); 44 continue; 45 } 46 } 47 break; 48 } 49 ret 50 } 51 from_ffi(inner: &'a HttpClientResponse) -> Self52 pub(crate) fn from_ffi(inner: &'a HttpClientResponse) -> Self { 53 Self { 54 inner: ResponseInner::Ref(inner), 55 } 56 } 57 from_shared(inner: SharedPtr<HttpClientTask>) -> Self58 pub(crate) fn from_shared(inner: SharedPtr<HttpClientTask>) -> Self { 59 Self { 60 inner: ResponseInner::Shared(inner), 61 } 62 } 63 } 64 65 enum ResponseInner<'a> { 66 Ref(&'a HttpClientResponse), 67 Shared(SharedPtr<HttpClientTask>), 68 } 69 70 impl<'a> ResponseInner<'a> { to_response(&self) -> &HttpClientResponse71 fn to_response(&self) -> &HttpClientResponse { 72 match self { 73 ResponseInner::Ref(inner) => inner, 74 ResponseInner::Shared(inner) => RequestTask::pin_mut(inner) 75 .GetResponse() 76 .into_ref() 77 .get_ref(), 78 } 79 } 80 } 81 82 #[derive(Clone, Default, PartialEq, Eq)] 83 pub enum ResponseCode { 84 #[default] 85 None = 0, 86 Ok = 200, 87 Created, 88 Accepted, 89 NotAuthoritative, 90 NoContent, 91 Reset, 92 Partial, 93 MultChoice = 300, 94 MovedPerm, 95 MovedTemp, 96 SeeOther, 97 NotModified, 98 UseProxy, 99 BadRequest = 400, 100 Unauthorized, 101 PaymentRequired, 102 Forbidden, 103 NotFound, 104 BadMethod, 105 NotAcceptable, 106 ProxyAuth, 107 ClientTimeout, 108 Conflict, 109 Gone, 110 LengthRequired, 111 PreconFailed, 112 EntityTooLarge, 113 ReqTooLong, 114 UnsupportedType, 115 InternalError = 500, 116 NotImplemented, 117 BadGateway, 118 Unavailable, 119 GatewayTimeout, 120 Version, 121 } 122