1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
|
//
// Copyright Aliaksei Levin (levlam@telegram.org), Arseny Smirnov (arseny30@gmail.com) 2014-2026
//
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
//
#include "td/net/DarwinHttp.h"
#include "td/utils/logging.h"
#include "td/utils/SliceBuilder.h"
#import <Foundation/Foundation.h>
namespace td {
namespace {
NSURLSession *getSession() {
static NSURLSession *urlSession = [] {
auto configuration = [NSURLSessionConfiguration defaultSessionConfiguration];
configuration.networkServiceType = NSURLNetworkServiceTypeResponsiveData;
configuration.timeoutIntervalForResource = 90;
configuration.waitsForConnectivity = true;
return [NSURLSession sessionWithConfiguration:configuration];
}();
return urlSession;
}
NSString *to_ns_string(CSlice slice) {
return [NSString stringWithUTF8String:slice.c_str()];
}
NSData *to_ns_data(Slice data) {
return [NSData dataWithBytes:static_cast<const void *>(data.data()) length:data.size()];
}
auto http_get(CSlice url) {
auto nsurl = [NSURL URLWithString:to_ns_string(url)];
auto request = [NSURLRequest requestWithURL:nsurl];
return request;
}
auto http_post(CSlice url, Slice data) {
auto nsurl = [NSURL URLWithString:to_ns_string(url)];
auto request = [NSMutableURLRequest requestWithURL:nsurl];
[request setHTTPMethod:@"POST"];
[request setHTTPBody:to_ns_data(data)];
[request setValue:@"keep-alive" forHTTPHeaderField:@"Connection"];
[request setValue:@"" forHTTPHeaderField:@"Host"];
[request setValue:to_ns_string(PSLICE() << data.size()) forHTTPHeaderField:@"Content-Length"];
[request setValue:@"application/x-www-form-urlencoded" forHTTPHeaderField:@"Content-Type"];
return request;
}
void http_send(NSURLRequest *request, Promise<std::pair<int32, BufferSlice>> promise) {
__block auto callback = std::move(promise);
NSURLSessionDataTask *dataTask =
[getSession()
dataTaskWithRequest:request
completionHandler:
^(NSData *data, NSURLResponse *response, NSError *error) {
if (error == nil) {
int32 statusCode = 0;
if ([response isKindOfClass:[NSHTTPURLResponse class]]) {
NSHTTPURLResponse *httpResponse = (NSHTTPURLResponse *)response;
statusCode = static_cast<int32>(httpResponse.statusCode);
}
callback.set_value(std::make_pair(statusCode, BufferSlice(Slice((const char *)([data bytes]), [data length]))));
} else {
callback.set_error(static_cast<int32>([error code]), "HTTP request failed");
}
}];
[dataTask resume];
}
} // namespace
void DarwinHttp::get(CSlice url, Promise<std::pair<int32, BufferSlice>> promise) {
return http_send(http_get(url), std::move(promise));
}
void DarwinHttp::post(CSlice url, Slice data, Promise<std::pair<int32, BufferSlice>> promise) {
return http_send(http_post(url, data), std::move(promise));
}
} // namespace td
|