Dostęp do Rails API z poziomu C++ [Część 1: zapytania GET]

Michał Brodecki 2015-05-07
W trakcie mojej pracy napotkałem potrzebę komunikacji pomiędzy aplikacjami napisanymi w Ruby on Rails a desktopowymi programami napisanymi w C++ (z wykorzystaniem biblioteki QT). Zbudowanie odpowiedniego rozwiązania wiązało się z kilkoma czasochłonnymi problemami. Dla tego postanowiłem przedstawić Wam kilka sztuczek, które pozwolą zaoszczędzić czas. :) Zamiast tworzyć jeden wielki wpis, podzieliłem temat na części. W pierwszej z nich przedstawię Wam podstawy tworzenia zapytań GET.

Zapytania GET pozwalają na wyciąganie informacji z serwera. Jeżeli dane tam są serwer powinien je zwrócić. Bardziej oficjalną definicję znajdziecie tutaj.

Zatem do dzieła!

Pokażę Wam tylko część kodu, całość możecie znaleźć na githubie (kod aplikacji C++, kod Rails Api). Kiedy będziecie mieli wszystko przygotowane trzeba skompilować aplikację C++ i odpalić 'rails server'.

Teraz wystarczy wpisać http://localhost:3000/entries/1 i wcisnąć przycisk 'Send request' - wasze pierwsze zapytanie GET jest gotowe. A wygląda to tak:

 Przyjrzyjmy się bliżej kodowi

Przykład wysyłania zapytania GET w C++ wygląda następująco:

QNetworkAccessManager * manager = new QNetworkAccessManager(this);
connect(manager, SIGNAL(finished(QNetworkReply*)), this,  SLOT(replyFinished(QNetworkReply*)));
manager->get(QNetworkRequest(QUrl(ui->urlLineEdit->text())));

QnetworkAccessManager jest klasą zaprojektowana do wysyłania zapytań sieciowych. Wywołując manager->get(QNetworkRequest(QUrl(ui->urlLineEdit->text()))); uzyskamy zapytanie dla odnośnika wziętego z paska adresu. Wraz z odpowiedzią QnetworkAccessManager wysyła sygnał 'Finished', który w moim przykładzie wiąże się ze slotem replyFinished.

Przykład otrzymywania odpowiedzi w C++:

void MainWindow::replyFinished(QNetworkReply * reply)
{
    ui->debugTextBrowser->append(tr("got reply"));
    QVariant statusCodeV =
    reply->attribute(QNetworkRequest::HttpStatusCodeAttribute);
    ui->debugTextBrowser->append("Status code: " + QString::number(statusCodeV.value()));
    // Or the target URL if it was a redirect:
    QVariant redirectionTargetUrl =
    reply->attribute(QNetworkRequest::RedirectionTargetAttribute);
    // see CS001432 on how to handle this
    if (reply->error() == QNetworkReply::NoError)
    {
        QByteArray bytes = reply->readAll();
        QString string(bytes);
        ui->resultTextBrowser->setText(string);
    }
    else
    {
        //handle errors
    }
    reply->deleteLater();
}

Jak widać odpowiedź uzyskujemy w formie QByteArray, którą można łatwo przetworzyć na QString używając konstruktora. Pamiętajcie, że ten kod nie wskaże błędów w połączeniu, a w zastosowaniach produkcyjnych powinien. Szczegółowe informacje o błędach można przekazać użytkownikom używając reply -> error() - przykład znajdziecie tutaj.

Zwróćcie uwagę, że w momencie wyzwalania slotu dziedziczy on odpowiedź obiektu, za ten slot jest odpowiedzialny za usunięcie odpowiedzi. Nie powinnismy usuwać jej bezpośrednio poprzez użycie funkcji delete reply, zamiast tego zalecane jest użycie deleteLater. Możemy uzyskać więcej szczegółów na temat samej odpowiedzi poprzez wywołanie reply->attribute<T>(QNetworkRequest::Attribute code). Na przykład możemy uzyskać status kodu poprzez wywołanie statusCodeV.value<int>() - pamiętajcie, że to jest metoda szablonu, dlatego należy zapewnić typ zwracanych danych. Pełną listę atrybutów QNetworkReply można znaleźć na stronie.

Podsumowanie

Wpis ten poruszył podstawy zapytań GET w języku C++. W następnym wpisie pokażę w jaki sposób przygotować format JSON w aplikacji RoR, jak go pobrać z wykorzystaniem metody GET oraz jak go parsować i wydobywać dane. Dziękuję za uwagę.

 

BinarApps

Wpis został opublikowany dzięki współpracy z firmą BinarApps. Więcej wpisów o Ruby znajdziesz na ich blogu www.binarapps.com/blog

Mogą Cię również zainteresować

comments powered by Disqus