Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Browse files

Get following redirects working

  • Loading branch information...
commit 6b49ec30af6a3aa6570853e7cef2e13515445a7f 1 parent 53619cf
@scotchi scotchi authored
Showing with 65 additions and 37 deletions.
  1. +49 −21 QActiveResource.cpp
  2. +1 −0  QActiveResource.h
  3. +15 −16 Ruby/QAR.cpp
View
70 QActiveResource.cpp
@@ -19,6 +19,20 @@ static size_t writer(void *ptr, size_t size, size_t nmemb, void *stream)
return size * nmemb;
}
+static size_t header(void *ptr, size_t size, size_t nmemb, void *stream)
+{
+ QByteArray header((const char *) ptr, size * nmemb);
+
+ QList<QByteArray> elements = header.split(' ');
+
+ if(elements[0] == "Location:" && elements.length() >= 2)
+ {
+ *reinterpret_cast<QByteArray *>(stream) = elements[1].simplified();
+ }
+
+ return size * nmemb;
+}
+
namespace HTTP
{
void handleError(int result, long httpCode, const QString &message)
@@ -72,42 +86,56 @@ namespace HTTP
throw Exception(type, message);
}
- QByteArray get(const QUrl &url, bool followRedirects = false)
+ QByteArray get(QUrl url, bool followRedirects = false)
{
QByteArray data;
CURL *curl = curl_easy_init();
- static const int maxRetry = 1;
- int retry = 0;
int result = 0;
if(curl)
{
QByteArray encodedUrl = url.toEncoded();
QByteArray errorBuffer(CURL_ERROR_SIZE, 0);
+ QByteArray location;
- do
- {
- curl_easy_setopt(curl, CURLOPT_URL, encodedUrl.data());
- curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, writer);
- curl_easy_setopt(curl, CURLOPT_WRITEDATA, (void *) &data);
- curl_easy_setopt(curl, CURLOPT_TIMEOUT, 25);
- curl_easy_setopt(curl, CURLOPT_NOSIGNAL, 1);
- curl_easy_setopt(curl, CURLOPT_ERRORBUFFER, errorBuffer.data());
-
- if(followRedirects)
- {
- curl_easy_setopt(curl, CURLOPT_FOLLOWLOCATION, 1);
- curl_easy_setopt(curl, CURLOPT_UNRESTRICTED_AUTH, 1);
- curl_easy_setopt(curl, CURLOPT_MAXREDIRS, 2);
- }
- }
- while((result = curl_easy_perform(curl)) != 0 && ++retry <= maxRetry);
+ curl_easy_setopt(curl, CURLOPT_URL, encodedUrl.data());
+ curl_easy_setopt(curl, CURLOPT_WRITEHEADER, (void *) &location);
+ curl_easy_setopt(curl, CURLOPT_HEADERFUNCTION, header);
+ curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, writer);
+ curl_easy_setopt(curl, CURLOPT_WRITEDATA, (void *) &data);
+ curl_easy_setopt(curl, CURLOPT_TIMEOUT, 25);
+ curl_easy_setopt(curl, CURLOPT_NOSIGNAL, 1);
+ curl_easy_setopt(curl, CURLOPT_ERRORBUFFER, errorBuffer.data());
+ curl_easy_setopt(curl, CURLOPT_SSL_VERIFYHOST, 0);
+
+ result = curl_easy_perform(curl);
long httpCode = 0;
curl_easy_getinfo(curl, CURLINFO_RESPONSE_CODE, &httpCode);
- if(result != 0 || httpCode >= 400)
+ if(httpCode >= 300 && httpCode < 400)
+ {
+ qDebug() << (followRedirects ? "Following" : "Not following") << "redirect from"
+ << url.toString(QUrl::RemoveUserInfo) << "to" << location;
+
+ curl_easy_cleanup(curl);
+
+ if(!followRedirects || location.isEmpty())
+ {
+ throw Exception(Exception::Redirection, location);
+ }
+ else
+ {
+ QString user = url.userName();
+ QString pass = url.password();
+ url = location;
+ url.setUserName(user);
+ url.setPassword(pass);
+ return get(url);
+ }
+ }
+ else if(result != 0 || httpCode >= 400)
{
QString message;
View
1  QActiveResource.h
@@ -19,6 +19,7 @@ namespace QActiveResource
ConnectionError,
TimeoutError,
SSLError,
+ Redirection,
ClientError,
BadRequest,
UnauthorizedAccess,
View
31 Ruby/QAR.cpp
@@ -3,7 +3,7 @@
* Copyright (C) 2010, Directed Edge, Inc. | Licensed under the MPL and LGPL
*/
-#include "../QActiveResource.h"
+#include <QActiveResource.h>
#include <QDateTime>
#include <QDebug>
#include <ruby.h>
@@ -35,6 +35,7 @@ static const ID _allocate = rb_intern("allocate");
static const ID _at = rb_intern("at");
static const ID _collection_name = rb_intern("collection_name");
static const ID _element_name = rb_intern("element_name");
+static const ID _extend = rb_intern("extend");
static const ID _first = rb_intern("first");
static const ID _from = rb_intern("from");
static const ID _new = rb_intern("new");
@@ -51,7 +52,7 @@ static const ID _last = rb_intern("last");
static const ID __attributes = rb_intern("@attributes");
static const ID __prefix_options = rb_intern("@prefix_options");
-static const ID __qar_resource = rb_intern("@qar_resource");
+static const ID __qar_resource = rb_intern("@@qar_resource");
static QString to_s(VALUE value)
{
@@ -167,27 +168,16 @@ static int params_hash_iterator(VALUE key, VALUE value, VALUE params)
static QActiveResource::Resource *get_resource(VALUE self)
{
- VALUE member = rb_ivar_get(self, __qar_resource);
+ VALUE member = rb_cvar_get(self, __qar_resource);
QActiveResource::Resource *resource = 0;
-
- if(member == Qnil)
- {
- member = rb_funcall(rb_cQARResource, _new, 0);
- rb_ivar_set(self, __qar_resource, member);
- Data_Get_Struct(member, QActiveResource::Resource, resource);
- resource->setBase(to_s(rb_funcall(self, _site, 0)));
- }
- else
- {
- Data_Get_Struct(member, QActiveResource::Resource, resource);
- }
-
+ Data_Get_Struct(member, QActiveResource::Resource, resource);
return resource;
}
static VALUE qar_find(int argc, VALUE *argv, VALUE self)
{
QActiveResource::Resource *resource = get_resource(self);
+ resource->setBase(to_s(rb_funcall(self, _site, 0)));
QString from;
@@ -264,6 +254,7 @@ static VALUE qar_find(int argc, VALUE *argv, VALUE self)
AR_TEST_EXCEPTION(ConnectionError);
AR_TEST_EXCEPTION(TimeoutError);
AR_TEST_EXCEPTION(SSLError);
+ AR_TEST_EXCEPTION(Redirection);
AR_TEST_EXCEPTION(ClientError);
AR_TEST_EXCEPTION(BadRequest);
AR_TEST_EXCEPTION(UnauthorizedAccess);
@@ -285,6 +276,13 @@ static VALUE set_follow_redirects(VALUE self, VALUE follow)
return follow;
}
+static VALUE qar_extended(VALUE self, VALUE base)
+{
+ VALUE resource = rb_funcall(rb_cQARResource, _new, 0);
+ rb_cvar_set(base, __qar_resource, resource, false);
+ return Qnil;
+}
+
extern "C"
{
void Init_QAR(void)
@@ -302,5 +300,6 @@ extern "C"
rb_define_method(rb_mQAR, "find", (ARGS) qar_find, -1);
rb_define_method(rb_mQAR, "follow_redirects=", (ARGS) set_follow_redirects, 1);
+ rb_define_singleton_method(rb_mQAR, "extended", (ARGS) qar_extended, 1);
}
}
Please sign in to comment.
Something went wrong with that request. Please try again.