diff --git a/integration-box/http/README.md b/integration-box/http/README.md new file mode 100644 index 00000000..48f02382 --- /dev/null +++ b/integration-box/http/README.md @@ -0,0 +1,30 @@ +# Treasure Data Streaming Ingest API + +Treasure Data Streaming Ingest API allows you to ingest data through HTTPS. + +## Overview + +In the multiple programming languages, this Box shows its basic usage by sequentially inserting two records: + +|id|name|age|comment|object|array| +|:---:|:---:|:---:|:---:|:---:|:---:| +|1|John Doe|25|hello, world|{'lang', 'xxx'}|['hello', 'world']| +|2|Jane Doe|23|good morning|{'lang', 'xxx'}|['good', 'morning']| + +## Usage + +First, edit [`config.sample.json`](./config.sample.json) and rename as `config.json`. + +As you can see, the `events` part of JSON payload represents single record (i.e., row) stored in Treasure Data: + +```json +{ + "events": [{ + "column_name_1": (value_1), + "column_name_2": (value_2), + ... + }, ...] +} +``` + +Eventually, the records will become available on your target Treasure Data table. diff --git a/integration-box/http/c/README.md b/integration-box/http/c/README.md new file mode 100644 index 00000000..c8799ebc --- /dev/null +++ b/integration-box/http/c/README.md @@ -0,0 +1,12 @@ +# Treasure Data HTTP ingest: C Example + +## Usage + +### C with libcurl + +An C source code example with [libcurl](https://curl.haxx.se/libcurl/) + +``` +cc -lcurl curl.c +./a.out c360-ingest-api.treasuredata.com 1/123456789abcdefghijklmnopqrstuvwxyz database_name table_name '{"events":[{"name":"John"}]}' +``` diff --git a/integration-box/http/c/curl.c b/integration-box/http/c/curl.c new file mode 100644 index 00000000..08c3238e --- /dev/null +++ b/integration-box/http/c/curl.c @@ -0,0 +1,94 @@ +#include +#include +#include + +int main(int argc, char *argv[]) +{ + CURLcode ret; + CURL *hnd; + struct curl_slist *slist1; + + if (argc != 6) { + fprintf(stderr, "usage: %s \n", argv[0]); + } + + /* c360-ingest-api endpoint; ex. "c360-ingest-api.treasuredata.com" */ + char *endpoint = argv[1]; + /* Treasure Data apikey; ex. "1234/0123456789abcdef0123456789abcdef01234567 */ + char *apikey = argv[2]; + /* Treasure Data database name; pattern: [0-9a-z_]{3,128} */ + char *database = argv[3]; + /* Treasure Data table name; pattern: [0-9a-z_]{3,128} */ + char *table = argv[4]; + /* payload: + * { + * "events": [ + * {"key": "value", ...}, + * ... + * ] + * } + */ + char *curlopt_postfields = argv[5]; + + char curlopt_url[1024]; + { + int r = snprintf(curlopt_url, sizeof(curlopt_url), "https://%s/%s/%s", endpoint, database, table); + if (r <= 0 || 1000 < r) { + fprintf(stderr, "failed to format curlopt_url\n"); + exit(1); + } + } + + char authrization[128]; + { + int r = snprintf(authrization, sizeof(authrization), "Authorization: TD1 %s", apikey); + if (r <= 0 || 100 < r) { + fprintf(stderr, "failed to format Authorization\n"); + exit(1); + } + } + + slist1 = NULL; + slist1 = curl_slist_append(slist1, "Content-Type: application/vnd.treasuredata.v1+json"); + slist1 = curl_slist_append(slist1, "Accept: application/vnd.treasuredata.v1+json"); + slist1 = curl_slist_append(slist1, authrization); + + hnd = curl_easy_init(); + curl_easy_setopt(hnd, CURLOPT_URL, curlopt_url); + curl_easy_setopt(hnd, CURLOPT_NOPROGRESS, 1L); + curl_easy_setopt(hnd, CURLOPT_POSTFIELDS, curlopt_postfields); + curl_easy_setopt(hnd, CURLOPT_POSTFIELDSIZE_LARGE, (curl_off_t)strlen(curlopt_postfields)); + curl_easy_setopt(hnd, CURLOPT_USERAGENT, "curl/7.54.0"); + curl_easy_setopt(hnd, CURLOPT_HTTPHEADER, slist1); + curl_easy_setopt(hnd, CURLOPT_MAXREDIRS, 50L); + curl_easy_setopt(hnd, CURLOPT_HTTP_VERSION, (long)CURL_HTTP_VERSION_2TLS); + curl_easy_setopt(hnd, CURLOPT_TCP_KEEPALIVE, 1L); + + /* Here is a list of options the curl code used that cannot get generated + as source easily. You may select to either not use them or implement + them yourself. + + CURLOPT_WRITEDATA set to a objectpointer + CURLOPT_INTERLEAVEDATA set to a objectpointer + CURLOPT_WRITEFUNCTION set to a functionpointer + CURLOPT_READDATA set to a objectpointer + CURLOPT_READFUNCTION set to a functionpointer + CURLOPT_SEEKDATA set to a objectpointer + CURLOPT_SEEKFUNCTION set to a functionpointer + CURLOPT_ERRORBUFFER set to a objectpointer + CURLOPT_STDERR set to a objectpointer + CURLOPT_HEADERFUNCTION set to a functionpointer + CURLOPT_HEADERDATA set to a objectpointer + + */ + + ret = curl_easy_perform(hnd); + + curl_easy_cleanup(hnd); + hnd = NULL; + curl_slist_free_all(slist1); + slist1 = NULL; + + return (int)ret; +} +/**** End of sample code ****/ diff --git a/integration-box/http/config.sample.json b/integration-box/http/config.sample.json new file mode 100644 index 00000000..edbe1278 --- /dev/null +++ b/integration-box/http/config.sample.json @@ -0,0 +1,6 @@ +{ + "endpoint": "c360-ingest-api.treasuredata.com", + "apikey": "1/123456789abcdefghijklmnopqrstuvwxyz", + "database": "database_name", + "table": "table_name" +} diff --git a/integration-box/http/ruby/README.md b/integration-box/http/ruby/README.md new file mode 100644 index 00000000..eb8cb7a1 --- /dev/null +++ b/integration-box/http/ruby/README.md @@ -0,0 +1,7 @@ +# Treasure Data HTTP ingest: Ruby Example + +## Usage + +``` +ruby http.rb +``` diff --git a/integration-box/http/ruby/http.rb b/integration-box/http/ruby/http.rb new file mode 100755 index 00000000..90824b73 --- /dev/null +++ b/integration-box/http/ruby/http.rb @@ -0,0 +1,39 @@ +#!/usr/bin/env ruby +require 'json' +require 'net/http' + +config_path = File.expand_path('../config.sample.json', __dir__) +config = JSON.parse(File.read(config_path)) + + +path = "/#{config['database']}/#{config['table']}" + +payload = { + events: [ + { + name: 'John Doe', + age: 25, + comment: 'hello, world', + object: {lang: 'ruby'}, + array: %w[hello world] + }, + { + name: 'Jane Done', + age: 23, + comment: 'good morning', + object: {lang: 'ruby'}, + array: %w[good morning] + }, + ] +} + +Net::HTTP.start(config["endpoint"], 443, use_ssl: true) do |http| + headers = { + "Authorization" => "TD1 #{config["apikey"]}", + "Content-Type" => "application/vnd.treasuredata.v1+json", + "Accept" => "application/vnd.treasuredata.v1+json", + } + res = http.post(path, JSON.dump(payload), headers) + p res + puts res.body +end