Skip to content

Commit a87f575

Browse files
committed
fix: some options were not allowing to be set to null
1 parent 6a7a882 commit a87f575

File tree

3 files changed

+83
-48
lines changed

3 files changed

+83
-48
lines changed

CHANGELOG.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,8 @@ and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0.
99
### Fixed
1010
- Fix `curly.post` and `curly.head` using wrong libcurl options to set the HTTP Method.
1111
- Fix `postinstall` script not working properly.
12+
- Setting the `HTTPPOST` option to `null`would, wrongly, throw an Error.
13+
- Setting any string option to `null` would, wrongly, throw an Error.
1214
### Added
1315
- Added back prebuilt binaries for:
1416
- Electron v3, v4 and v5

src/Easy.cc

Lines changed: 44 additions & 48 deletions
Original file line numberDiff line numberDiff line change
@@ -430,7 +430,8 @@ size_t Easy::OnData(char* data, size_t size, size_t nmemb) {
430430
int32_t returnValue = -1;
431431

432432
const int argc = 3;
433-
v8::Local<v8::Object> buf = Nan::CopyBuffer(data, static_cast<uint32_t>(dataLength)).ToLocalChecked();
433+
v8::Local<v8::Object> buf =
434+
Nan::CopyBuffer(data, static_cast<uint32_t>(dataLength)).ToLocalChecked();
434435
v8::Local<v8::Uint32> sizeArg = Nan::New<v8::Uint32>(static_cast<uint32_t>(size));
435436
v8::Local<v8::Uint32> nmembArg = Nan::New<v8::Uint32>(static_cast<uint32_t>(nmemb));
436437

@@ -485,7 +486,8 @@ size_t Easy::OnHeader(char* data, size_t size, size_t nmemb) {
485486
int32_t returnValue = -1;
486487

487488
const int argc = 3;
488-
v8::Local<v8::Object> buf = Nan::CopyBuffer(data, static_cast<uint32_t>(dataLength)).ToLocalChecked();
489+
v8::Local<v8::Object> buf =
490+
Nan::CopyBuffer(data, static_cast<uint32_t>(dataLength)).ToLocalChecked();
489491
v8::Local<v8::Uint32> sizeArg = Nan::New<v8::Uint32>(static_cast<uint32_t>(size));
490492
v8::Local<v8::Uint32> nmembArg = Nan::New<v8::Uint32>(static_cast<uint32_t>(nmemb));
491493

@@ -1107,8 +1109,11 @@ NAN_METHOD(Easy::SetOpt) {
11071109
}
11081110
// linked list options
11091111
} else if ((optionId = IsInsideCurlConstantStruct(curlOptionLinkedList, opt))) {
1110-
// HTTPPOST is a special case, since it's an array of objects.
1111-
if (optionId == CURLOPT_HTTPPOST) {
1112+
if (value->IsNull()) {
1113+
setOptRetCode = curl_easy_setopt(obj->ch, static_cast<CURLoption>(optionId), NULL);
1114+
1115+
// HTTPPOST is a special case, since it's an array of objects.
1116+
} else if (optionId == CURLOPT_HTTPPOST) {
11121117
std::string invalidArrayMsg = "HTTPPOST option value should be an Array of Objects.";
11131118

11141119
if (!value->IsArray()) {
@@ -1258,66 +1263,57 @@ NAN_METHOD(Easy::SetOpt) {
12581263
}
12591264

12601265
} else {
1261-
if (value->IsNull()) {
1262-
setOptRetCode = curl_easy_setopt(obj->ch, static_cast<CURLoption>(optionId), NULL);
1263-
1264-
} else {
1265-
if (!value->IsArray()) {
1266-
Nan::ThrowTypeError("Option value must be an Array.");
1267-
return;
1268-
}
1266+
if (!value->IsArray()) {
1267+
Nan::ThrowTypeError("Option value must be an Array.");
1268+
return;
1269+
}
12691270

1270-
// convert value to curl linked list (curl_slist)
1271-
curl_slist* slist = NULL;
1272-
v8::Local<v8::Array> array = v8::Local<v8::Array>::Cast(value);
1271+
// convert value to curl linked list (curl_slist)
1272+
curl_slist* slist = NULL;
1273+
v8::Local<v8::Array> array = v8::Local<v8::Array>::Cast(value);
12731274

1274-
for (uint32_t i = 0, len = array->Length(); i < len; ++i) {
1275-
slist = curl_slist_append(slist, *Nan::Utf8String(Nan::Get(array, i).ToLocalChecked()));
1276-
}
1275+
for (uint32_t i = 0, len = array->Length(); i < len; ++i) {
1276+
slist = curl_slist_append(slist, *Nan::Utf8String(Nan::Get(array, i).ToLocalChecked()));
1277+
}
12771278

1278-
setOptRetCode = curl_easy_setopt(obj->ch, static_cast<CURLoption>(optionId), slist);
1279+
setOptRetCode = curl_easy_setopt(obj->ch, static_cast<CURLoption>(optionId), slist);
12791280

1280-
if (setOptRetCode == CURLE_OK) {
1281-
obj->toFree->slist.push_back(slist);
1282-
}
1281+
if (setOptRetCode == CURLE_OK) {
1282+
obj->toFree->slist.push_back(slist);
12831283
}
12841284
}
1285-
12861285
// check if option is string, and the value is correct
12871286
} else if ((optionId = IsInsideCurlConstantStruct(curlOptionString, opt))) {
1288-
if (!value->IsString()) {
1289-
Nan::ThrowTypeError("Option value must be a string.");
1290-
return;
1291-
}
1292-
1293-
// Create a string copy
1294-
bool isNull = value->IsNull();
1295-
1296-
if (isNull) {
1287+
if (value->IsNull()) {
12971288
setOptRetCode = curl_easy_setopt(obj->ch, static_cast<CURLoption>(optionId), NULL);
1298-
}
1289+
} else {
1290+
if (!value->IsString()) {
1291+
Nan::ThrowTypeError("Option value must be a string.");
1292+
return;
1293+
}
12991294

1300-
Nan::Utf8String value(info[1]);
1295+
Nan::Utf8String value(info[1]);
13011296

1302-
size_t length = static_cast<size_t>(value.length());
1297+
size_t length = static_cast<size_t>(value.length());
13031298

1304-
std::string valueStr = std::string(*value, length);
1299+
std::string valueStr = std::string(*value, length);
13051300

1306-
// libcurl makes a copy of the strings after version 7.17, CURLOPT_POSTFIELD
1307-
// is the only exception
1308-
if (static_cast<CURLoption>(optionId) == CURLOPT_POSTFIELDS) {
1309-
std::vector<char> valueChar = std::vector<char>(valueStr.begin(), valueStr.end());
1310-
valueChar.push_back(0);
1301+
// libcurl makes a copy of the strings after version 7.17, CURLOPT_POSTFIELD
1302+
// is the only exception
1303+
if (static_cast<CURLoption>(optionId) == CURLOPT_POSTFIELDS) {
1304+
std::vector<char> valueChar = std::vector<char>(valueStr.begin(), valueStr.end());
1305+
valueChar.push_back(0);
13111306

1312-
setOptRetCode = curl_easy_setopt(obj->ch, static_cast<CURLoption>(optionId), &valueChar[0]);
1307+
setOptRetCode = curl_easy_setopt(obj->ch, static_cast<CURLoption>(optionId), &valueChar[0]);
13131308

1314-
if (setOptRetCode == CURLE_OK) {
1315-
obj->toFree->str.push_back(std::move(valueChar));
1316-
}
1309+
if (setOptRetCode == CURLE_OK) {
1310+
obj->toFree->str.push_back(std::move(valueChar));
1311+
}
13171312

1318-
} else {
1319-
setOptRetCode =
1320-
curl_easy_setopt(obj->ch, static_cast<CURLoption>(optionId), valueStr.c_str());
1313+
} else {
1314+
setOptRetCode =
1315+
curl_easy_setopt(obj->ch, static_cast<CURLoption>(optionId), valueStr.c_str());
1316+
}
13211317
}
13221318

13231319
// check if option is an integer, and the value is correct

test/curl/setOpt.spec.ts

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,23 @@ describe('setOpt()', () => {
4040
curl.setOpt(Curl.option.URL, url)
4141
})
4242

43+
it('should be able to set string value back to null', () => {
44+
curl.setOpt('URL', url)
45+
curl.setOpt('URL', null)
46+
})
47+
48+
it('should be able to set integer value back to null', () => {
49+
curl.setOpt('ACCEPTTIMEOUT_MS', 30000)
50+
curl.setOpt('ACCEPTTIMEOUT_MS', null)
51+
})
52+
53+
it('should be able to set function value back to null', () => {
54+
curl.setOpt('WRITEFUNCTION', () => {
55+
return 0
56+
})
57+
curl.setOpt('WRITEFUNCTION', null)
58+
})
59+
4360
it('should not accept invalid argument type', () => {
4461
const optionsToTest = [
4562
['URL', 0],
@@ -119,6 +136,26 @@ describe('setOpt()', () => {
119136
})
120137

121138
describe('HTTPPOST', () => {
139+
it('should work', () => {
140+
curl.setOpt('HTTPPOST', [
141+
{
142+
name: 'field',
143+
contents: 'value',
144+
},
145+
])
146+
})
147+
148+
it('should be able to set option back to null', () => {
149+
curl.setOpt('HTTPPOST', [
150+
{
151+
name: 'field',
152+
contents: 'value',
153+
},
154+
])
155+
156+
curl.setOpt('HTTPPOST', null)
157+
})
158+
122159
it('should not accept invalid arrays', () => {
123160
try {
124161
// @ts-ignore

0 commit comments

Comments
 (0)