summaryrefslogtreecommitdiff
path: root/src/couch/priv/couch_js/http.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/couch/priv/couch_js/http.cpp')
-rw-r--r--src/couch/priv/couch_js/http.cpp201
1 files changed, 103 insertions, 98 deletions
diff --git a/src/couch/priv/couch_js/http.cpp b/src/couch/priv/couch_js/http.cpp
index c38799dc3..5b0be0a71 100644
--- a/src/couch/priv/couch_js/http.cpp
+++ b/src/couch/priv/couch_js/http.cpp
@@ -41,10 +41,10 @@ http_ctor(JSContext* cx, JSObject* req)
}
-bool
-http_dtor(JSContext* cx, JSObject* req)
+void
+http_dtor(JSFreeOp* fop, JSObject* req)
{
- return false;
+ return;
}
@@ -70,7 +70,7 @@ http_send(JSContext* cx, JSObject* req, JS::Value body)
int
-http_status(JSContext* cx, JSObject* req, JS::Value body)
+http_status(JSContext* cx, JSObject* req)
{
return -1;
}
@@ -111,11 +111,11 @@ typedef struct {
int method;
char* url;
CurlHeaders* req_headers;
- jsint last_status;
+ int16_t last_status;
} HTTPData;
-char* METHODS[] = {"GET", "HEAD", "POST", "PUT", "DELETE", "COPY", "OPTIONS", NULL};
+const char* METHODS[] = {"GET", "HEAD", "POST", "PUT", "DELETE", "COPY", "OPTIONS", NULL};
#define GET 0
@@ -144,7 +144,7 @@ http_ctor(JSContext* cx, JSObject* req)
http = (HTTPData*) malloc(sizeof(HTTPData));
if(!http)
{
- JS_ReportError(cx, "Failed to create CouchHTTP instance.");
+ JS_ReportErrorUTF8(cx, "Failed to create CouchHTTP instance.");
goto error;
}
@@ -153,13 +153,9 @@ http_ctor(JSContext* cx, JSObject* req)
http->req_headers = NULL;
http->last_status = -1;
- if(!JS_SetPrivate(cx, req, http))
- {
- JS_ReportError(cx, "Failed to set private CouchHTTP data.");
- goto error;
- }
+ JS_SetPrivate(req, http);
- ret = JS_TRUE;
+ ret = true;
goto success;
error:
@@ -171,9 +167,9 @@ success:
void
-http_dtor(JSContext* cx, JSObject* obj)
+http_dtor(JSFreeOp* fop, JSObject* obj)
{
- HTTPData* http = (HTTPData*) JS_GetPrivate(cx, obj);
+ HTTPData* http = (HTTPData*) JS_GetPrivate(obj);
if(http) {
if(http->url) free(http->url);
if(http->req_headers) curl_slist_free_all(http->req_headers);
@@ -185,24 +181,24 @@ http_dtor(JSContext* cx, JSObject* obj)
bool
http_open(JSContext* cx, JSObject* req, JS::Value mth, JS::Value url, JS::Value snc)
{
- HTTPData* http = (HTTPData*) JS_GetPrivate(cx, req);
+ HTTPData* http = (HTTPData*) JS_GetPrivate(req);
char* method = NULL;
int methid;
bool ret = false;
if(!http) {
- JS_ReportError(cx, "Invalid CouchHTTP instance.");
+ JS_ReportErrorUTF8(cx, "Invalid CouchHTTP instance.");
goto done;
}
- if(JSVAL_IS_VOID(mth)) {
- JS_ReportError(cx, "You must specify a method.");
+ if(mth.isUndefined()) {
+ JS_ReportErrorUTF8(cx, "You must specify a method.");
goto done;
}
method = enc_string(cx, mth, NULL);
if(!method) {
- JS_ReportError(cx, "Failed to encode method.");
+ JS_ReportErrorUTF8(cx, "Failed to encode method.");
goto done;
}
@@ -211,14 +207,14 @@ http_open(JSContext* cx, JSObject* req, JS::Value mth, JS::Value url, JS::Value
}
if(methid > OPTIONS) {
- JS_ReportError(cx, "Invalid method specified.");
+ JS_ReportErrorUTF8(cx, "Invalid method specified.");
goto done;
}
http->method = methid;
- if(JSVAL_IS_VOID(url)) {
- JS_ReportError(cx, "You must specify a URL.");
+ if(url.isUndefined()) {
+ JS_ReportErrorUTF8(cx, "You must specify a URL.");
goto done;
}
@@ -229,12 +225,12 @@ http_open(JSContext* cx, JSObject* req, JS::Value mth, JS::Value url, JS::Value
http->url = enc_string(cx, url, NULL);
if(http->url == NULL) {
- JS_ReportError(cx, "Failed to encode URL.");
+ JS_ReportErrorUTF8(cx, "Failed to encode URL.");
goto done;
}
- if(JSVAL_IS_BOOLEAN(snc) && JSVAL_TO_BOOLEAN(snc)) {
- JS_ReportError(cx, "Synchronous flag must be false.");
+ if(snc.isBoolean() && snc.isTrue()) {
+ JS_ReportErrorUTF8(cx, "Synchronous flag must be false.");
goto done;
}
@@ -246,7 +242,7 @@ http_open(JSContext* cx, JSObject* req, JS::Value mth, JS::Value url, JS::Value
// Disable Expect: 100-continue
http->req_headers = curl_slist_append(http->req_headers, "Expect:");
- ret = JS_TRUE;
+ ret = true;
done:
if(method) free(method);
@@ -257,7 +253,7 @@ done:
bool
http_set_hdr(JSContext* cx, JSObject* req, JS::Value name, JS::Value val)
{
- HTTPData* http = (HTTPData*) JS_GetPrivate(cx, req);
+ HTTPData* http = (HTTPData*) JS_GetPrivate(req);
char* keystr = NULL;
char* valstr = NULL;
char* hdrbuf = NULL;
@@ -265,47 +261,47 @@ http_set_hdr(JSContext* cx, JSObject* req, JS::Value name, JS::Value val)
bool ret = false;
if(!http) {
- JS_ReportError(cx, "Invalid CouchHTTP instance.");
+ JS_ReportErrorUTF8(cx, "Invalid CouchHTTP instance.");
goto done;
}
- if(JSVAL_IS_VOID(name))
+ if(name.isUndefined())
{
- JS_ReportError(cx, "You must speciy a header name.");
+ JS_ReportErrorUTF8(cx, "You must speciy a header name.");
goto done;
}
keystr = enc_string(cx, name, NULL);
if(!keystr)
{
- JS_ReportError(cx, "Failed to encode header name.");
+ JS_ReportErrorUTF8(cx, "Failed to encode header name.");
goto done;
}
- if(JSVAL_IS_VOID(val))
+ if(val.isUndefined())
{
- JS_ReportError(cx, "You must specify a header value.");
+ JS_ReportErrorUTF8(cx, "You must specify a header value.");
goto done;
}
valstr = enc_string(cx, val, NULL);
if(!valstr)
{
- JS_ReportError(cx, "Failed to encode header value.");
+ JS_ReportErrorUTF8(cx, "Failed to encode header value.");
goto done;
}
hdrlen = strlen(keystr) + strlen(valstr) + 3;
hdrbuf = (char*) malloc(hdrlen * sizeof(char));
if(!hdrbuf) {
- JS_ReportError(cx, "Failed to allocate header buffer.");
+ JS_ReportErrorUTF8(cx, "Failed to allocate header buffer.");
goto done;
}
snprintf(hdrbuf, hdrlen, "%s: %s", keystr, valstr);
http->req_headers = curl_slist_append(http->req_headers, hdrbuf);
- ret = JS_TRUE;
+ ret = true;
done:
if(keystr) free(keystr);
@@ -317,20 +313,20 @@ done:
bool
http_send(JSContext* cx, JSObject* req, JS::Value body)
{
- HTTPData* http = (HTTPData*) JS_GetPrivate(cx, req);
+ HTTPData* http = (HTTPData*) JS_GetPrivate(req);
char* bodystr = NULL;
size_t bodylen = 0;
bool ret = false;
if(!http) {
- JS_ReportError(cx, "Invalid CouchHTTP instance.");
+ JS_ReportErrorUTF8(cx, "Invalid CouchHTTP instance.");
goto done;
}
- if(!JSVAL_IS_VOID(body)) {
+ if(!body.isUndefined()) {
bodystr = enc_string(cx, body, &bodylen);
if(!bodystr) {
- JS_ReportError(cx, "Failed to encode body.");
+ JS_ReportErrorUTF8(cx, "Failed to encode body.");
goto done;
}
}
@@ -345,10 +341,10 @@ done:
int
http_status(JSContext* cx, JSObject* req)
{
- HTTPData* http = (HTTPData*) JS_GetPrivate(cx, req);
+ HTTPData* http = (HTTPData*) JS_GetPrivate(req);
if(!http) {
- JS_ReportError(cx, "Invalid CouchHTTP instance.");
+ JS_ReportErrorUTF8(cx, "Invalid CouchHTTP instance.");
return false;
}
@@ -363,28 +359,29 @@ http_uri(JSContext* cx, JSObject* req, couch_args* args, JS::Value* uri_val)
// Default is http://localhost:15986/ when no uri file is specified
if (!args->uri_file) {
- uri_str = JS_InternString(cx, "http://localhost:15986/");
- *uri_val = STRING_TO_JSVAL(uri_str);
- JS_SetReservedSlot(cx, req, 0, *uri_val);
- return JS_TRUE;
+ uri_str = JS_NewStringCopyZ(cx, "http://localhost:15986/");
+ *uri_val = JS::StringValue(uri_str);
+ JS_SetReservedSlot(req, 0, *uri_val);
+ return true;
}
// Else check to see if the base url is cached in a reserved slot
- if (JS_GetReservedSlot(cx, req, 0, uri_val) && !JSVAL_IS_VOID(*uri_val)) {
- return JS_TRUE;
+ *uri_val = JS_GetReservedSlot(req, 0);
+ if (!(*uri_val).isUndefined()) {
+ return true;
}
// Read the first line of the couch.uri file.
if(!((uri_fp = fopen(args->uri_file, "r")) &&
(uri_str = couch_readline(cx, uri_fp)))) {
- JS_ReportError(cx, "Failed to read couch.uri file.");
+ JS_ReportErrorUTF8(cx, "Failed to read couch.uri file.");
goto error;
}
fclose(uri_fp);
- *uri_val = STRING_TO_JSVAL(uri_str);
- JS_SetReservedSlot(cx, req, 0, *uri_val);
- return JS_TRUE;
+ *uri_val = JS::StringValue(uri_str);
+ JS_SetReservedSlot(req, 0, *uri_val);
+ return true;
error:
if(uri_fp) fclose(uri_fp);
@@ -427,7 +424,10 @@ go(JSContext* cx, JSObject* obj, HTTPData* http, char* body, size_t bodylen)
JSString* jsbody;
bool ret = false;
JS::Value tmp;
-
+ JS::RootedObject robj(cx, obj);
+ JS::RootedValue vobj(cx);
+
+
state.cx = cx;
state.http = http;
@@ -456,25 +456,25 @@ go(JSContext* cx, JSObject* obj, HTTPData* http, char* body, size_t bodylen)
}
if(!HTTP_HANDLE) {
- JS_ReportError(cx, "Failed to initialize cURL handle.");
- goto done;
+ JS_ReportErrorUTF8(cx, "Failed to initialize cURL handle.");
+ if(state.recvbuf) JS_free(cx, state.recvbuf);
+ return ret;
}
- if(!JS_GetReservedSlot(cx, obj, 0, &tmp)) {
- JS_ReportError(cx, "Failed to readreserved slot.");
- goto done;
- }
+ tmp = JS_GetReservedSlot(obj, 0);
if(!(referer = enc_string(cx, tmp, NULL))) {
- JS_ReportError(cx, "Failed to encode referer.");
- goto done;
+ JS_ReportErrorUTF8(cx, "Failed to encode referer.");
+ if(state.recvbuf) JS_free(cx, state.recvbuf);
+ return ret;
}
curl_easy_setopt(HTTP_HANDLE, CURLOPT_REFERER, referer);
free(referer);
if(http->method < 0 || http->method > OPTIONS) {
- JS_ReportError(cx, "INTERNAL: Unknown method.");
- goto done;
+ JS_ReportErrorUTF8(cx, "INTERNAL: Unknown method.");
+ if(state.recvbuf) JS_free(cx, state.recvbuf);
+ return ret;
}
curl_easy_setopt(HTTP_HANDLE, CURLOPT_CUSTOMREQUEST, METHODS[http->method]);
@@ -506,25 +506,28 @@ go(JSContext* cx, JSObject* obj, HTTPData* http, char* body, size_t bodylen)
curl_easy_setopt(HTTP_HANDLE, CURLOPT_WRITEDATA, &state);
if(curl_easy_perform(HTTP_HANDLE) != 0) {
- JS_ReportError(cx, "Failed to execute HTTP request: %s", ERRBUF);
- goto done;
+ JS_ReportErrorUTF8(cx, "Failed to execute HTTP request: %s", ERRBUF);
+ if(state.recvbuf) JS_free(cx, state.recvbuf);
+ return ret;
}
if(!state.resp_headers) {
- JS_ReportError(cx, "Failed to recieve HTTP headers.");
- goto done;
+ JS_ReportErrorUTF8(cx, "Failed to recieve HTTP headers.");
+ if(state.recvbuf) JS_free(cx, state.recvbuf);
+ return ret;
}
+ tmp = JS::ObjectValue(*state.resp_headers);
+ JS::RootedValue rtmp(cx, tmp);
- tmp = OBJECT_TO_JSVAL(state.resp_headers);
if(!JS_DefineProperty(
- cx, obj,
+ cx, robj,
"_headers",
- tmp,
- NULL, NULL,
+ rtmp,
JSPROP_READONLY
)) {
- JS_ReportError(cx, "INTERNAL: Failed to set response headers.");
- goto done;
+ JS_ReportErrorUTF8(cx, "INTERNAL: Failed to set response headers.");
+ if(state.recvbuf) JS_free(cx, state.recvbuf);
+ return ret;;
}
if(state.recvbuf) {
@@ -533,34 +536,35 @@ go(JSContext* cx, JSObject* obj, HTTPData* http, char* body, size_t bodylen)
if(!jsbody) {
// If we can't decode the body as UTF-8 we forcefully
// convert it to a string by just forcing each byte
- // to a jschar.
+ // to a char16_t.
jsbody = str_from_binary(cx, state.recvbuf, state.read);
if(!jsbody) {
if(!JS_IsExceptionPending(cx)) {
- JS_ReportError(cx, "INTERNAL: Failed to decode body.");
+ JS_ReportErrorUTF8(cx, "INTERNAL: Failed to decode body.");
}
- goto done;
+ if(state.recvbuf) JS_free(cx, state.recvbuf);
+ return ret;
}
}
- tmp = STRING_TO_JSVAL(jsbody);
+ tmp = JS::StringValue(jsbody);
} else {
tmp = JS_GetEmptyStringValue(cx);
}
-
+
+ JS::RootedValue rtmp2(cx, tmp);
+
if(!JS_DefineProperty(
- cx, obj,
+ cx, robj,
"responseText",
- tmp,
- NULL, NULL,
+ rtmp2,
JSPROP_READONLY
)) {
- JS_ReportError(cx, "INTERNAL: Failed to set responseText.");
- goto done;
+ JS_ReportErrorUTF8(cx, "INTERNAL: Failed to set responseText.");
+ if(state.recvbuf) JS_free(cx, state.recvbuf);
+ return ret;
}
- ret = JS_TRUE;
-
-done:
+ ret = true;
if(state.recvbuf) JS_free(cx, state.recvbuf);
return ret;
}
@@ -609,9 +613,8 @@ recv_header(void *ptr, size_t size, size_t nmem, void *data)
char* header = (char*) ptr;
size_t length = size * nmem;
JSString* hdr = NULL;
- jsuint hdrlen;
- JS::Value hdrval;
-
+ uint32_t hdrlen;
+
if(length > 7 && strncasecmp(header, "HTTP/1.", 7) == 0) {
if(length < 12) {
return CURLE_WRITE_ERROR;
@@ -621,7 +624,7 @@ recv_header(void *ptr, size_t size, size_t nmem, void *data)
code[3] = '\0';
state->http->last_status = atoi(code);
- state->resp_headers = JS_NewArrayObject(state->cx, 0, NULL);
+ state->resp_headers = JS_NewArrayObject(state->cx, 0);
if(!state->resp_headers) {
return CURLE_WRITE_ERROR;
}
@@ -640,12 +643,13 @@ recv_header(void *ptr, size_t size, size_t nmem, void *data)
return CURLE_WRITE_ERROR;
}
- if(!JS_GetArrayLength(state->cx, state->resp_headers, &hdrlen)) {
+ JS::RootedObject obj(state->cx, state->resp_headers);
+ if(!JS_GetArrayLength(state->cx, obj, &hdrlen)) {
return CURLE_WRITE_ERROR;
}
- hdrval = STRING_TO_JSVAL(hdr);
- if(!JS_SetElement(state->cx, state->resp_headers, hdrlen, &hdrval)) {
+ JS::RootedString hdrval(state->cx, hdr);
+ if(!JS_SetElement(state->cx, obj, hdrlen, hdrval)) {
return CURLE_WRITE_ERROR;
}
@@ -662,7 +666,7 @@ recv_body(void *ptr, size_t size, size_t nmem, void *data)
if(!state->recvbuf) {
state->recvlen = 4096;
state->read = 0;
- state->recvbuf = JS_malloc(state->cx, state->recvlen);
+ state->recvbuf = (char *)JS_malloc(state->cx, state->recvlen);
}
if(!state->recvbuf) {
@@ -670,8 +674,9 @@ recv_body(void *ptr, size_t size, size_t nmem, void *data)
}
// +1 so we can add '\0' back up in the go function.
+ size_t oldlen = state->recvlen;
while(length+1 > state->recvlen - state->read) state->recvlen *= 2;
- tmp = JS_realloc(state->cx, state->recvbuf, state->recvlen);
+ tmp = (char *) JS_realloc(state->cx, state->recvbuf, oldlen, state->recvlen);
if(!tmp) return CURLE_WRITE_ERROR;
state->recvbuf = tmp;
@@ -683,14 +688,14 @@ recv_body(void *ptr, size_t size, size_t nmem, void *data)
JSString*
str_from_binary(JSContext* cx, char* data, size_t length)
{
- jschar* conv = (jschar*) JS_malloc(cx, length * sizeof(jschar));
+ char16_t* conv = (char16_t*) JS_malloc(cx, length * sizeof(char16_t));
JSString* ret = NULL;
size_t i;
if(!conv) return NULL;
for(i = 0; i < length; i++) {
- conv[i] = (jschar) data[i];
+ conv[i] = (char16_t) data[i];
}
ret = JS_NewUCString(cx, conv, length);