Skip to content

Commit

Permalink
chore: rework most examples
Browse files Browse the repository at this point in the history
  • Loading branch information
JCMais committed May 20, 2019
1 parent e97e323 commit 1b43e92
Show file tree
Hide file tree
Showing 37 changed files with 736 additions and 414 deletions.
58 changes: 36 additions & 22 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,22 +7,25 @@ and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0.
## [Unreleased]
### Breaking Change
- Dropped support for Node.js 4 and 6
- Prebuilt binary is now built statically with libssh2, nghttp2, OpenSSL and zlib. OpenSSL, nghttp2 and zlib versions match their respective versions used by Node.js.
- The minimum libcurl version being tested is now `7.50.0`, which itself is almost 3 years old.
- Prebuilt binary is now statically built with brotli, libssh2, nghttp2, OpenSSL and zlib. brotli, OpenSSL, nghttp2 and zlib versions match their respective versions used by Node.js.
- The minimum libcurl version being tested is now `7.50.0`, which itself is almost 3 years old.
The addon will still try to be compatible with old versions up to `7.32.0`, but there are no guarantees.
- `Curl.reset` now correctly resets their instance (#141)
- Previously `Curl.code` had all Curl codes into a single enum like object, that is, it included properties for each `CURLMCode`, `CURLcode` and `CURLSHcode` libcurl enums.

- `Curl.reset` now correctly resets their instance ([#141](https://github.com/JCMais/node-libcurl/pull/141))
- Previously `Curl.code` had all Curl codes into a single enum like object, that is, it included properties for each `CURLMCode`, `CURLcode` and `CURLSHcode` libcurl enums.
Now they are separated, each on their own object:
`CURLMCode` -> `Multi.code`
`CURLMCode -> Multi.code`
`CURLcode` -> `Curl.code`
`CURLSHCode` -> `Share.code`
- `DEBUGFUNCTION` now receives a `Buffer` as the `data` argument, instead of a `string`.
- `Easy.send` and `Easy.recv` now return an object, `{ code: CurlCode, bytesSent: number }` and `{ code: CurlCode, bytesReceived: number }` respectively.
- `_` prefix of `Curl` class private members has been removed, this is only a breaking change in case you were using internal methods.
- Removed deprecated `onData` and `onHeader` instance fields, use options `WRITEFUNCTION` and `HEADERFUNCTION` respectively.
- Prototype functions `onData` and `onHeader` renamed to `defaultWriteFunction` and `defaultHeaderFunction`
- `Curl.dupHandle`, argument `shouldCopyCallbacks` was removed, it was the first one.
- `Curl` class: removed `_` prefix from their private members.
Only a breaking change in case you were using internal methods.
- `Curl` class: methods `onData` and `onHeader` renamed to `defaultWriteFunction` and `defaultHeaderFunction`.
Only a breaking change in case you were using internal methods.
- `Curl` class: deprecated instance fields `onData` and `onHeader` were removed.
Use options `WRITEFUNCTION` and `HEADERFUNCTION` respectively.
- `Curl.dupHandle`, argument `shouldCopyCallbacks` was removed, it was the first one.
This is not needed anymore because the previously set callbacks (`onData` and `onHeader`) can now only be set using their respective libcurl options, which is always copied when duplicating a handle.
- `Curl.multi` moved to `Multi.option`
- `Curl.share` moved to `Share.option`
- Following members were moved to their own export:
Expand All @@ -49,13 +52,16 @@ and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0.
`Curl.sslversion.max` -> `CurlSslVersionMax`
`Curl.ssh_auth` -> `CurlSshAuth`
`Curl.timecond` -> `CurlTimeCond`
And their fields were changed from `SNAKE_CASE` to `PascalCase` (changed to follow Typescript's Enum naming conventions)
- `Curl.protocol` moved to their own export `CurlProtocol`, no changes were made to fields casing in this case.
- Passing non-integer option value to `Multi.setOpt` will now throw an error, previously the value was converted to `1` if it was a truthy value, or `0` if otherwise.
`Easy.socket` -> `SocketState`
And their fields were changed from `SNAKE_CASE` to `PascalCase`.
The change in casing was to follow Typescript's Enum naming convention.
- `Curl.protocol` also moved to their own export `CurlProtocol`, no changes were made to fields casing in this case.
- Passing non-integer option value to `Multi.setOpt` will now throw an error.
Previously the value was converted to `1` if it was a truthy value, or `0` if otherwise.
### Fixed
- Fix SigAbort caused by calling v8 AsFunction on null value at Easy::SetOpt
- Fix SegFault during gargage collection after process.exit (#165)
- Using `curl_socket_t` without libcurl version guard on Easy::GetInfo
- Fix SigAbort caused by calling v8 `AsFunction` on null value at `Easy::SetOpt`
- Fix SegFault during gargage collection after `process.exit` ([#165](https://github.com/JCMais/node-libcurl/issues/165))
- Using `curl_socket_t` without libcurl version guard on `Easy::GetInfo`
### Added
- Support Node.js 12
- Added missing options:
Expand All @@ -81,15 +87,20 @@ and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0.
- `CURLINFO_*_{DOWNLOAD,UPLOAD}_T`
- `CURLINFO_*_TIME_T`
- `CURLINFO_FILETIME_T`
- Add `Curl.getVersionInfo()` which returns an object that represents the struct returned from `curl_version_info()`
See their type definition for details: [`./lib/types/CurlVersionInfoNativeBinding.ts`](./lib/types/CurlVersionInfoNativeBinding.ts)
- Add `Curl.getVersionInfo()` which returns an object that represents the struct returned from `curl_version_info()`.
See their type definition for details: [`./lib/types/CurlVersionInfoNativeBinding.ts`](./lib/types/
- Add `Curl.getVersionInfoString()` which returns a string representation of the above function.
It should be almost identical to the one returned from `curl -V`.
- Add `Curl.isVersionGreaterOrEqualThan(x, y, z)` to help test if the libcurl version the addon was built against is greater or equal than x.y.z.
- Add `upkeep` function to Easy and Curl classes. This is a binding for the `curl_easy_upkeep()` function.
- Errors thrown inside callbacks are correctly caught / passed forward (if using multi interface)
- Added **experimental** `curl.<http-verb>()` async api
- All `Curl` instances now set their `USERAGENT` to `node-libcurl/${packageVersion}` during creation.
You change the default user agent string by changing `Curl.defaultUserAgent`, and disable it by setting their value to null.
- Added **experimental** `curly(url: string, options: {})` / `curly.<http-verb>(url: string, options: {})` async api.
This API can change between minor releases.
### Changed
- Migrated project to Typescript and added type definitions
- Bumped libcurl version used on Windows to `7.64.1`, with `nghttp2` support
- Bumped libcurl version used on Windows to `7.64.1`, which has `nghttp2` support
- Added the `Curl` instance that emitted the event as the last param passed to events, can be useful if using anonymous functions as callback for the events.
Example:
```javascript
Expand All @@ -98,8 +109,11 @@ and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0.
// ...
})
```
- Fix erratic condition when setting option `HEADERFUNCTION` (#142)
- macOS libs should be linked against @rpath (#145)
- Fix erratic condition when setting option `HEADERFUNCTION` ([#142](https://github.com/JCMais/node-libcurl/pull/142))
- macOS libs should be linked against @rpath ([#145](https://github.com/JCMais/node-libcurl/pull/145))


Special Thanks to [@koskokos2](https://github.com/koskokos2) for their contributions to this release.

## [1.3.3]
### Added
Expand Down
102 changes: 102 additions & 0 deletions examples/01-curl.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,102 @@
/**
* Copyright (c) Jonathan Cardoso Machado. All Rights Reserved.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*/

/**
* Example showing how one could do a simple request using the `Curl` wrapper.
*
* The `Curl` class is just a wrapper around the `Easy` class, it has all their methods, but instead
* of being `sync`, it's `async`. This is achieved by using a `Multi` instance internally.
*/
const { Curl, CurlFeature } = require('../dist')

// by default all Curl instances set their user agent to `node-libcurl/${addonVersion}`
// when they are created
// you can change it using:
Curl.defaultUserAgent = 'Something Else'
// or simply remove it
Curl.defaultUserAgent = null

const curl = new Curl()

// if you want to change the user agent for an already created instance you will need
// to use their respective libcurl option, USERAGENT

// can pass the url via argument to this example. node examples/01-simple-request.js http://www.example.com
const url = process.argv[2] || 'http://www.google.com'

// you can use the option name directly
curl.setOpt('URL', url)

// or use an already defined constant
curl.setOpt(Curl.option.CONNECTTIMEOUT, 5)
curl.setOpt(Curl.option.FOLLOWLOCATION, true)

// Enable verbose mode
curl.setOpt(Curl.option.VERBOSE, true)

// If you use an invalid option, a TypeError exception will be thrown

// By default, this can emit 4 events, `data`, `header`, `end` and `error`.
// events are emitted with `this` bound to the handle, however if you
// use an arrow function like below, you can still access the curl instance from the last argument

// The `chunk` argument passed to the `data` and `header` events are raw Buffer objects.
// The `body` argument passed to the `end` event is a string, which is the result of converting
// all received data chunks to a utf8 string.
// The `headers` one passed to the `end` event is an array of objects, it is an array because each redirect has their own
// headers, in case there were no redirects in the request or the `FOLLOWLOCATION` option was
// not used, the array will contain a single item.
// You can disable this automatic conversion of the `body` and `headers` on the `end` event by enabling some features
// on the `Curl` instance. For example:
curl.enable(CurlFeature.NoDataParsing)
curl.enable(CurlFeature.NoHeaderParsing)
// or just:
curl.enable(CurlFeature.Raw)

// that way the `end` event will receive the raw `Buffer` objects for `data` and `headers`.
// If you dont even want the `Curl` instance to store the data / headers, you can also enable features for that:
curl.enable(CurlFeature.NoDataStorage)
curl.enable(CurlFeature.NoHeaderStorage)
// or just:
curl.enable(CurlFeature.NoStorage)
// NoStorage imples Raw

// to get back to what it was before we can disable those features:
curl.disable(CurlFeature.Raw | CurlFeature.NoStorage)

curl.on('data', (chunk, curlInstance) => {
console.log('Receiving data with size: ', chunk.length)
})

curl.on('header', (chunk, curlInstance) => {
console.log('Receiving headers with size: ', chunk.length)
})

curl.on('end', (statusCode, body, headers, curlInstance) => {
console.info('Status Code: ', statusCode)
console.info('Headers: ', headers)
console.info('Body length: ', body.length)

// always close the `Curl` instance when you don't need it anymore
// Keep in mind we can do multiple requests with the same `Curl` instance
// before it's closed, we just need to set new options if needed
// and call `.perform()` again.
curl.close()
})

// Error will be a JS error, errorCode will be the raw error code (as int) returned from libcurl
curl.on('error', (error, errorCode) => {
console.error('Error: ', error)
console.error('Code: ', errorCode)
curl.close()
})

// this triggers the request
curl.perform()

// It's async, so it does not block the Node.js thread
console.log('I will show before the request starts')
48 changes: 48 additions & 0 deletions examples/02-easy.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
/**
* Copyright (c) Jonathan Cardoso Machado. All Rights Reserved.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*/

/**
* Example showing how one could do a simple request using the `Easy` handle.
*/
const { Curl, CurlCode, Easy } = require('../dist')

const url = process.argv[2] || 'http://www.google.com'

const handle = new Easy()

// Just like before, we can use the option name, or the constant
handle.setOpt('URL', url)
handle.setOpt(Curl.option.VERBOSE, url)

// This is used to receive the headers
// See https://curl.haxx.se/libcurl/c/CURLOPT_HEADERFUNCTION.html
handle.setOpt(Curl.option.HEADERFUNCTION, function(buf, size, nmemb) {
console.log('HEADERFUNCTION: ')
console.log(arguments)

return size * nmemb
})

// This is used to receive the headers
// See https://curl.haxx.se/libcurl/c/CURLOPT_WRITEFUNCTION.html
handle.setOpt(Curl.option.WRITEFUNCTION, function(buf, size, nmemb) {
console.log('WRITEFUNCTION: ')
console.log(arguments)

return size * nmemb
})

// this will trigger the request
const ret = handle.perform()
// The Easy handle will block the JS main thread:
console.log('I will only show after the request has finished')

// Remember to always close the handles
handle.close()

// In case there is something wrong, you can use Easy.strError to get a human readable string about the error
console.log(ret, ret === CurlCode.CURLE_OK, Easy.strError(ret))
70 changes: 70 additions & 0 deletions examples/03-curlx.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
/**
* Copyright (c) Jonathan Cardoso Machado. All Rights Reserved.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*/

/**
* Example showing how one could do a simple request using the `curlx` async fn
*/
const querystring = require('querystring')

const { curly } = require('../dist')

const run = async () => {
try {
// there are many ways to use the curly.* functions
let response = null

// 1. Calling directly, which will default to a GET
console.log('==================== REQUEST #1 ====================')
response = await curly('http://www.httpbin.org/get')
console.log(response.statusCode, response.headers, response.data)

// 2. Using the curly.<http-verb> functions

// get
console.log('==================== REQUEST #2 ====================')
response = await curly.get('http://www.httpbin.org/get')
console.log(response.statusCode, response.headers, response.data)

// post
console.log('==================== REQUEST #3 ====================')
const dataToSend = {
//Data to send, inputName : value
'input-arr[0]': 'input-arr-val0',
'input-arr[1]': 'input-arr-val1',
'input-arr[2]': 'input-arr-val2',
'input-name': 'input-val',
}
response = await curly.post('http://httpbin.org/post', {
postFields: querystring.stringify(dataToSend),
// would work too:
// POSTFIELDS: querystring.stringify(dataToSend),
})
console.log(response.statusCode, response.headers, response.data)

// 3 - Using writeFunction / headerFunction instead
console.log('==================== REQUEST #4 ====================')
response = await curly.get('http://httpbin.org/get', {
writeFunction: (chunk, size, nmemb) => {
// do something with chunk, which is a Buffer
return size * nmemb
},
headerFunction: (chunk, size, nmemb) => {
// do something with chunk, which is a Buffer
return size * nmemb
},
})
// In this case headers will be an empty array and data will be a 0 length string
console.log(response.statusCode, response.headers, response.data)

// in case of errors, the libcurl error code will be inside `error.code`
await curly.get('http://www.non-existing-domain.com')
} catch (error) {
console.error(`Error: ${error.message} - Code: ${error.code}`)
}
}

run()
20 changes: 12 additions & 8 deletions examples/multi-interface.js → examples/04-multi.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,10 +6,12 @@
*/

/**
* Example showing how to use the Multi handle to make async requests.
* Example showing how to use the `Multi` handle to make async requests.
* The Multi handle is used internally by the `Curl` wrapper
*
* The methods should have a description, hover over them to see it on your editor
*/
const Easy = require('../lib/Easy')
const Multi = require('../lib/Multi')
const { Easy, Multi } = require('../dist')

const urls = [
'http://google.com',
Expand Down Expand Up @@ -53,23 +55,25 @@ multi.onMessage((error, handle, errorCode) => {
)
}

// we are done with this handle, remove it from the Multi instance and close it
multi.removeHandle(handle)
handle.close()

if (++finished === urls.length) {
console.log('Finished all requests!')
// remember to close the multi instance too, when you are done with it.
multi.close()
}
})

/**
* @param {Buffer} data
* @param {Number} n
* @param {Number} nmemb
* @returns {number}
* This will be used as callback for for WRITEFUNCTION
*
* data is a Buffer, n and nmemb are integers. You must return n * nmemb from this
* callback to let libcurl know you handled correctly all data received.
*/
function onData(data, n, nmemb) {
//this === the handle
// this === the handle
const key = handles.indexOf(this)

handlesData[key].push(data)
Expand Down
Loading

0 comments on commit 1b43e92

Please sign in to comment.