forked from angelali314159/MyStudySpace
-
Notifications
You must be signed in to change notification settings - Fork 0
/
curlUtils.h
151 lines (127 loc) · 4.78 KB
/
curlUtils.h
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
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
#include <iostream>
#include <string>
#include <map>
#include <vector>
#include <sstream>
#include <exception>
#include "json.h"
#include <curl/curl.h>
using namespace std;
using json = nlohmann::json;
// Written by Jingyi Fu
// catch exceptions for errors related to cURL operations
class CurlException : public exception {
private:
string errorMessage;
public:
CurlException(const string& message) : errorMessage(message) {}
const char* what() const noexcept override {
return errorMessage.c_str();
}
};
// catch exceptions when interacting with the Spotify API
class SpotifyException : public exception {
private:
string message;
public:
SpotifyException(const string& msg) : message(msg) {}
const char* what() const noexcept override {
return message.c_str();
}
};
// functions for handling data from Spotify API request
static size_t WriteCallback(void* contents, size_t size, size_t nmemb, string* userp) {
userp->append((char*)contents, size * nmemb);
return size * nmemb;
}
string Replace(string str, const string& from, const string& to) {
size_t start_pos = 0;
while ((start_pos = str.find(from, start_pos)) != string::npos) {
str.replace(start_pos, from.length(), to);
start_pos += to.length();
}
return str;
}
json SpotifyCurlInternal(const string& request, const string& endpoint, const map<string, string>& options, const string& authToken, const string& body = "") {
CURL* curl = curl_easy_init();
if (!curl) {
throw CurlException("Failed to initialize cURL");
}
string url = "https://api.spotify.com" + endpoint;
if (!options.empty()) {
url += "?";
for (const auto& option : options) {
url += option.first + "=" + Replace(option.second, " ", "%20") + '&';
}
url.pop_back(); // Remove the last '&' character
}
curl_slist* headers = nullptr;
string authHeader = "Authorization: Bearer " + authToken;
headers = curl_slist_append(headers, authHeader.c_str());
string readBuffer;
curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, WriteCallback);
curl_easy_setopt(curl, CURLOPT_WRITEDATA, &readBuffer);
curl_easy_setopt(curl, CURLOPT_URL, url.c_str());
curl_easy_setopt(curl, CURLOPT_CUSTOMREQUEST, request.c_str());
curl_easy_setopt(curl, CURLOPT_HTTPHEADER, headers);
if (!body.empty()) {
curl_easy_setopt(curl, CURLOPT_POSTFIELDS, body.c_str());
}
// debugger
//cout << "Request URL: " << url << endl;
CURLcode rc = curl_easy_perform(curl);
if (rc != CURLE_OK) {
string errorMessage = curl_easy_strerror(rc);
curl_easy_cleanup(curl);
curl_slist_free_all(headers);
throw CurlException(errorMessage);
}
long statusCode = 0;
curl_easy_getinfo(curl, CURLINFO_RESPONSE_CODE, &statusCode);
// debugger
if (statusCode < 200 || statusCode > 299) {
cout << "Response body: " << readBuffer << endl;
curl_easy_cleanup(curl);
curl_slist_free_all(headers);
if (!readBuffer.empty()) {
// Attempt to parse the error message from Spotify
try {
json errorJson = json::parse(readBuffer);
string errorMsg = errorJson.value("error", "Unknown error occurred");
throw SpotifyException("HTTP Error: Status code " + to_string(statusCode) + " - " + errorMsg);
} catch (const json::exception& e) {
// parsing fails
throw SpotifyException("HTTP Error: Status code " + to_string(statusCode) + " - Failed to parse error response");
}
} else {
throw SpotifyException("HTTP Error: Status code " + to_string(statusCode));
}
}
curl_easy_cleanup(curl);
curl_slist_free_all(headers);
try {
return json::parse(readBuffer);
} catch (json::parse_error& e) {
throw SpotifyException("JSON Parse Error: " + string(e.what()));
}
}
/* spotify api requests
code adapted from the nlohmann::json library
*/
// SPOTIFY GET //
json SpotifyGET(string endpoint, map<string, string> options, string authToken, string body = ""){
return SpotifyCurlInternal("GET", endpoint, options, authToken, body);
}
// SPOTIFY POST//
json SpotifyPOST(string endpoint, map<string, string> options, string authToken, string body = ""){
return SpotifyCurlInternal("POST", endpoint, options, authToken, body);
}
// SPOTIFY PUT //
json SpotifyPUT(string endpoint, map<string, string> options, string authToken, string body = "")
{
return SpotifyCurlInternal("PUT", endpoint, options, authToken, body);
}
// SPOTIFY DELETE //
json SpotifyDELETE(string endpoint, map<string, string> options, string authToken, string body = ""){
return SpotifyCurlInternal("DELETE", endpoint, options, authToken, body);
}