Discussion:
[Wt-interest] RESTful service example...
Plug Gulp
2012-05-29 07:02:39 UTC
Permalink
Hi,

Please forgive my lack of knowledge on both web-development and Wt. I
am an embedded software engineer and new to both Wt and web
development. I am trying to learn Wt. Since last couple of days I have
been trying to understand how to implement RESTful API using Wt. But
with no success.

How do I implement a RESTful service using Wt? Say, I want to
implement a simple RESTful API:

http://www.example.com/hello

This API should return the data "Hello World!". How do I achieve this using Wt?

I read on the mailing list that WResource is used to implement RESTful
service in Wt. So I wrote the following code to implement the above
API:

////////////////////////////////////////

#include <Wt/WServer>
#include <Wt/WResource>
#include <Wt/Http/Response>

using namespace Wt;

class RestGetHello : public Wt::WResource
{
public:
virtual ~RestGetHello(){}

protected:
virtual void handleRequest(const Wt::Http::Request &request,
Wt::Http::Response &response)
{
response.out() << "Hello World!\n";
}
};

#if defined(WITH_WAPP)
class RestApplication : public WApplication
{
public:
RestApplication(const WEnvironment& env)
: WApplication(env)
{
WServer::instance()->addResource(&getHello, "/hello");
}

private:
RestGetHello getHello;
};

WApplication *createApplication(const WEnvironment& env)
{
return new RestApplication(env);
}
#endif

int main(int argc, char **argv)
{
#if defined(WITH_WAPP)
return Wt::WRun(argc, argv, &createApplication);
#else
try {
WServer server(argv[0]);

server.setServerConfiguration(argc, argv);

RestGetHello getHello;

server.addResource(&getHello, "/hello");

if (server.start()) {
WServer::waitForShutdown();
server.stop();
}
} catch (WServer::Exception& e) {
std::cerr << e.what() << std::endl;
} catch (std::exception &e) {
std::cerr << "exception: " << e.what() << std::endl;
}
#endif
}

///////////////////////////////////////

I am using the following command to access this API:

curl http://www.example.com/hello

But all that I get is the content of an HTML page generated by Wt. I
am attaching with this e-mail the output of the above command. Please
could you provide example on how to implement RESTful service using
Wt?

Thanks and regards,

~Plug
Nagaev Boris
2012-05-29 08:37:20 UTC
Permalink
Hello!

I changed your code to work as expected:

1. remove #if macros
2. remove call of Wt::WRun, which used to prevent the program to enter
try-catch.
3. remove RestApplication class (which is not needed for this example)
4. add beingDeleted(); to ~RestGetHello() (as as stated in documentation)
Post by Plug Gulp
Hi,
Please forgive my lack of knowledge on both web-development and Wt. I
am an embedded software engineer and new to both Wt and web
development. I am trying to learn Wt. Since last couple of days I have
been trying to understand how to implement RESTful API using Wt. But
with no success.
How do I implement a RESTful service using Wt? Say, I want to
http://www.example.com/hello
This API should return the data "Hello World!". How do I achieve this using Wt?
I read on the mailing list that WResource is used to implement RESTful
service in Wt. So I wrote the following code to implement the above
////////////////////////////////////////
#include <Wt/WServer>
#include <Wt/WResource>
#include <Wt/Http/Response>
using namespace Wt;
class RestGetHello : public Wt::WResource
{
       virtual ~RestGetHello(){}
       virtual void handleRequest(const Wt::Http::Request &request,
Wt::Http::Response &response)
       {
           response.out() << "Hello World!\n";
       }
};
#if defined(WITH_WAPP)
class RestApplication : public WApplication
{
       RestApplication(const WEnvironment& env)
           : WApplication(env)
       {
           WServer::instance()->addResource(&getHello, "/hello");
       }
       RestGetHello getHello;
};
WApplication *createApplication(const WEnvironment& env)
{
   return new RestApplication(env);
}
#endif
int main(int argc, char **argv)
{
#if defined(WITH_WAPP)
   return Wt::WRun(argc, argv, &createApplication);
#else
   try {
       WServer server(argv[0]);
       server.setServerConfiguration(argc, argv);
       RestGetHello getHello;
       server.addResource(&getHello, "/hello");
       if (server.start()) {
           WServer::waitForShutdown();
           server.stop();
       }
   } catch (WServer::Exception& e) {
       std::cerr << e.what() << std::endl;
   } catch (std::exception &e) {
       std::cerr << "exception: " << e.what() << std::endl;
   }
#endif
}
///////////////////////////////////////
curl http://www.example.com/hello
But all that I get is the content of an HTML page generated by Wt. I
am attaching with this e-mail the output of the above command. Please
could you provide example on how to implement RESTful service using
Wt?
Thanks and regards,
~Plug
------------------------------------------------------------------------------
Live Security Virtual Conference
Exclusive live event will cover all the ways today's security and
threat landscape has changed and how IT managers can respond. Discussions
will include endpoint security, mobile security and the latest in malware
threats. http://www.accelacomm.com/jaw/sfrnl04242012/114/50122263/
_______________________________________________
witty-interest mailing list
https://lists.sourceforge.net/lists/listinfo/witty-interest
Alec Taylor
2012-05-29 08:50:24 UTC
Permalink
Quick related on RESTful exposure with Wt:

Is there a full user-auth stack integrated with Wt?

E.g.: can I setup routes and whatnot based on which role the user who
attempts to access the API is?
Post by Nagaev Boris
Hello!
1. remove #if macros
2. remove call of Wt::WRun, which used to prevent the program to enter
try-catch.
3. remove RestApplication class (which is not needed for this example)
4. add beingDeleted(); to ~RestGetHello() (as as stated in documentation)
Post by Plug Gulp
Hi,
Please forgive my lack of knowledge on both web-development and Wt. I
am an embedded software engineer and new to both Wt and web
development. I am trying to learn Wt. Since last couple of days I have
been trying to understand how to implement RESTful API using Wt. But
with no success.
How do I implement a RESTful service using Wt? Say, I want to
http://www.example.com/hello
This API should return the data "Hello World!". How do I achieve this using Wt?
I read on the mailing list that WResource is used to implement RESTful
service in Wt. So I wrote the following code to implement the above
////////////////////////////////////////
#include <Wt/WServer>
#include <Wt/WResource>
#include <Wt/Http/Response>
using namespace Wt;
class RestGetHello : public Wt::WResource
{
       virtual ~RestGetHello(){}
       virtual void handleRequest(const Wt::Http::Request &request,
Wt::Http::Response &response)
       {
           response.out() << "Hello World!\n";
       }
};
#if defined(WITH_WAPP)
class RestApplication : public WApplication
{
       RestApplication(const WEnvironment& env)
           : WApplication(env)
       {
           WServer::instance()->addResource(&getHello, "/hello");
       }
       RestGetHello getHello;
};
WApplication *createApplication(const WEnvironment& env)
{
   return new RestApplication(env);
}
#endif
int main(int argc, char **argv)
{
#if defined(WITH_WAPP)
   return Wt::WRun(argc, argv, &createApplication);
#else
   try {
       WServer server(argv[0]);
       server.setServerConfiguration(argc, argv);
       RestGetHello getHello;
       server.addResource(&getHello, "/hello");
       if (server.start()) {
           WServer::waitForShutdown();
           server.stop();
       }
   } catch (WServer::Exception& e) {
       std::cerr << e.what() << std::endl;
   } catch (std::exception &e) {
       std::cerr << "exception: " << e.what() << std::endl;
   }
#endif
}
///////////////////////////////////////
curl http://www.example.com/hello
But all that I get is the content of an HTML page generated by Wt. I
am attaching with this e-mail the output of the above command. Please
could you provide example on how to implement RESTful service using
Wt?
Thanks and regards,
~Plug
------------------------------------------------------------------------------
Live Security Virtual Conference
Exclusive live event will cover all the ways today's security and
threat landscape has changed and how IT managers can respond. Discussions
will include endpoint security, mobile security and the latest in malware
threats. http://www.accelacomm.com/jaw/sfrnl04242012/114/50122263/
_______________________________________________
witty-interest mailing list
https://lists.sourceforge.net/lists/listinfo/witty-interest
------------------------------------------------------------------------------
Live Security Virtual Conference
Exclusive live event will cover all the ways today's security and
threat landscape has changed and how IT managers can respond. Discussions
will include endpoint security, mobile security and the latest in malware
threats. http://www.accelacomm.com/jaw/sfrnl04242012/114/50122263/
_______________________________________________
witty-interest mailing list
https://lists.sourceforge.net/lists/listinfo/witty-interest
Nagaev Boris
2012-05-29 09:02:58 UTC
Permalink
Post by Alec Taylor
Is there a full user-auth stack integrated with Wt?
Wt::Auth (authentication, not authorization), which can be used in
conjunction with Wt::Dbo (databases)

http://www.webtoolkit.eu/wt/doc/reference/html/group__auth.html
http://www.webtoolkit.eu/wt/doc/reference/html/group__dbo.html

Introduction to Wt::Auth:
http://www.webtoolkit.eu/wt/doc/tutorial/auth.html
Post by Alec Taylor
E.g.: can I setup routes and whatnot based on which role the user who
attempts to access the API is?
Wt::Auth is used to be sure, that user is actually the person, which
he is claims to be (authentication). To implement Roles
(authorization, e.g. user permissions to do smth), you should
implement your own class and connect it to Wt::Auth (see AuthInfo
class).

http://www.webtoolkit.eu/wt/doc/reference/html/classWt_1_1Auth_1_1Dbo_1_1AuthInfo.html
Post by Alec Taylor
Post by Nagaev Boris
Hello!
1. remove #if macros
2. remove call of Wt::WRun, which used to prevent the program to enter
try-catch.
3. remove RestApplication class (which is not needed for this example)
4. add beingDeleted(); to ~RestGetHello() (as as stated in documentation)
Post by Plug Gulp
Hi,
Please forgive my lack of knowledge on both web-development and Wt. I
am an embedded software engineer and new to both Wt and web
development. I am trying to learn Wt. Since last couple of days I have
been trying to understand how to implement RESTful API using Wt. But
with no success.
How do I implement a RESTful service using Wt? Say, I want to
http://www.example.com/hello
This API should return the data "Hello World!". How do I achieve this using Wt?
I read on the mailing list that WResource is used to implement RESTful
service in Wt. So I wrote the following code to implement the above
////////////////////////////////////////
#include <Wt/WServer>
#include <Wt/WResource>
#include <Wt/Http/Response>
using namespace Wt;
class RestGetHello : public Wt::WResource
{
       virtual ~RestGetHello(){}
       virtual void handleRequest(const Wt::Http::Request &request,
Wt::Http::Response &response)
       {
           response.out() << "Hello World!\n";
       }
};
#if defined(WITH_WAPP)
class RestApplication : public WApplication
{
       RestApplication(const WEnvironment& env)
           : WApplication(env)
       {
           WServer::instance()->addResource(&getHello, "/hello");
       }
       RestGetHello getHello;
};
WApplication *createApplication(const WEnvironment& env)
{
   return new RestApplication(env);
}
#endif
int main(int argc, char **argv)
{
#if defined(WITH_WAPP)
   return Wt::WRun(argc, argv, &createApplication);
#else
   try {
       WServer server(argv[0]);
       server.setServerConfiguration(argc, argv);
       RestGetHello getHello;
       server.addResource(&getHello, "/hello");
       if (server.start()) {
           WServer::waitForShutdown();
           server.stop();
       }
   } catch (WServer::Exception& e) {
       std::cerr << e.what() << std::endl;
   } catch (std::exception &e) {
       std::cerr << "exception: " << e.what() << std::endl;
   }
#endif
}
///////////////////////////////////////
curl http://www.example.com/hello
But all that I get is the content of an HTML page generated by Wt. I
am attaching with this e-mail the output of the above command. Please
could you provide example on how to implement RESTful service using
Wt?
Thanks and regards,
~Plug
------------------------------------------------------------------------------
Live Security Virtual Conference
Exclusive live event will cover all the ways today's security and
threat landscape has changed and how IT managers can respond. Discussions
will include endpoint security, mobile security and the latest in malware
threats. http://www.accelacomm.com/jaw/sfrnl04242012/114/50122263/
_______________________________________________
witty-interest mailing list
https://lists.sourceforge.net/lists/listinfo/witty-interest
------------------------------------------------------------------------------
Live Security Virtual Conference
Exclusive live event will cover all the ways today's security and
threat landscape has changed and how IT managers can respond. Discussions
will include endpoint security, mobile security and the latest in malware
threats. http://www.accelacomm.com/jaw/sfrnl04242012/114/50122263/
_______________________________________________
witty-interest mailing list
https://lists.sourceforge.net/lists/listinfo/witty-interest
------------------------------------------------------------------------------
Live Security Virtual Conference
Exclusive live event will cover all the ways today's security and
threat landscape has changed and how IT managers can respond. Discussions
will include endpoint security, mobile security and the latest in malware
threats. http://www.accelacomm.com/jaw/sfrnl04242012/114/50122263/
_______________________________________________
witty-interest mailing list
https://lists.sourceforge.net/lists/listinfo/witty-interest
Plug Gulp
2012-05-29 10:00:50 UTC
Permalink
@Nagaev
No, it does not work. Are you trying the example with the wthttp
server that comes with Wt or are you trying this with FCGI connector?
I am using Apache+fcgid and it does not work for me. If you try to
access the example "hello" RESTful API mentioned in my original post,
you will get an html page back (refer the output file attached with
the original post). If you want to understand what actually happens
when that RESTful API is invoked, try accessing it via Firefox instead
of cURL. When you access the API via Firefox, there are actually 6
requests sent to the server (5 GET and 1 POST). These extra request
are injected by Wt. Also the URL is modified by Wt to include
sessionID and other parameters. The WResource is not created and
registered until after the first few GET requests that Wt generates.
Even after that the handleRequest method of the resource is never
called because the EntryPoint deduced by Wt for any of the 6 requests
is never of type StaticResource. So I am missing something here. Its
not just the code, it is also about how to invoke the RESTful API for
Wt service. It will be helpful if someone can point me to a simple
"hello world" RESTful service example that works under FCGI connector.
Post by Nagaev Boris
1. remove #if macros
Well if you do not define WITH_APP then you get essentially what you
suggest in following two points.
Post by Nagaev Boris
2. remove call of Wt::WRun, which used to prevent the program to enter try-catch.
3. remove RestApplication class (which is not needed for this example)
Just don't define WITH_APP and it should be okay.
Post by Nagaev Boris
4. add beingDeleted(); to ~RestGetHello() (as as stated in documentation)
Yep, missed that. Thanks!

Kind regards,

~Plug
Nagaev Boris
2012-05-29 10:42:48 UTC
Permalink
Post by Plug Gulp
@Nagaev
No, it does not work. Are you trying the example with the wthttp
server that comes with Wt or are you trying this with FCGI connector?
I used with wthttp.

$ md5sum 1.cpp
af1ee4b949a63e8071a20e393077ee92 1.cpp

Compilation:
$ g++ 1.cpp -o 1 -lwt -lwthttp

Run:
$ ./1 --http-port 8000 --http-address 0.0.0.0 --docroot .

Access:
$ curl http://0.0.0.0:8000/hello
Hello World!

It should work.

For static resources, no extra requests are performed: you just get
(through HTTP) output of handleRequest.

It should work as well with any type of connector (fcgi or isapi) or
when wthttp is used through reverse proxy (like nginx or apache
http_proxy).

But it is not how RESTful API should be implemented for Wt.
imho, you should use normal WApplication and connect
internalPathChanged() signal to handler function, that would create
WText("Hello");

In this case you'll get additional requests (application
initialization, javascript, etc).
And "Hello" would not be raw HTTP contents (as in 1.cpp), but a part of HTML.

Full example see attached file 2.cpp

When I click the anchor, URL is changed to http://0.0.0.0:8000/#/hello/
I other browsers (and Wt versions) it could be
http://0.0.0.0:8000?_=/hello/ or http://0.0.0.0:8000/hello/
It should also work through fcgi or http proxy (some configuration may
be needed).
Post by Plug Gulp
I am using Apache+fcgid and it does not work for me. If you try to
access the example "hello" RESTful API mentioned in my original post,
you will get an html page back (refer the output file attached with
the original post). If you want to understand what actually happens
when that RESTful API is invoked, try accessing it via Firefox instead
of cURL. When you access the API via Firefox, there are actually 6
requests sent to the server (5 GET and 1 POST). These extra request
are injected by Wt. Also the URL is modified by Wt to include
sessionID and other parameters. The WResource is not created and
registered until after the first few GET requests that Wt generates.
Even after that the handleRequest method of the resource is never
called because the EntryPoint deduced by Wt for any of the 6 requests
is never of type StaticResource. So I am missing something here. Its
not just the code, it is also about how to invoke the RESTful API for
Wt service. It will be helpful if someone can point me to a simple
"hello world" RESTful service example that works under FCGI connector.
Post by Nagaev Boris
1. remove #if macros
Well if you do not define WITH_APP then you get essentially what you
suggest in following two points.
Ok, I did not notice that :)
Post by Plug Gulp
Post by Nagaev Boris
2. remove call of Wt::WRun, which used to prevent the program to enter try-catch.
3. remove RestApplication class (which is not needed for this example)
Just don't define WITH_APP and it should be okay.
Post by Nagaev Boris
4. add beingDeleted(); to ~RestGetHello() (as as stated in documentation)
Yep, missed that. Thanks!
Kind regards,
~Plug
------------------------------------------------------------------------------
Live Security Virtual Conference
Exclusive live event will cover all the ways today's security and
threat landscape has changed and how IT managers can respond. Discussions
will include endpoint security, mobile security and the latest in malware
threats. http://www.accelacomm.com/jaw/sfrnl04242012/114/50122263/
_______________________________________________
witty-interest mailing list
https://lists.sourceforge.net/lists/listinfo/witty-interest
Plug Gulp
2012-05-29 13:36:02 UTC
Permalink
@Nagaev
Post by Nagaev Boris
$ g++ 1.cpp -o 1 -lwt -lwthttp
$ ./1 --http-port 8000 --http-address 0.0.0.0 --docroot .
$ curl http://0.0.0.0:8000/hello
Hello World!
It should work.
Yep, it worked! Thank you very much!
Post by Nagaev Boris
For static resources, no extra requests are performed: you just get
(through HTTP) output of handleRequest.
It should work as well with any type of connector (fcgi or isapi) or
when wthttp is used through reverse proxy (like nginx or apache
http_proxy).
There is a slight change from how the RESTful API is accessed when
using via FCGI connector. For the example code used above, the URI for
accessing the resource via FCGI connector will then be:

curl http://0.0.0.0:8000/1.wt/hello

instead of

curl http://0.0.0.0:8000/hello

which is valid for (only?) wthttp. Thanks to Koen for pointing that
out on the Wt help mailing list (post title: "Non-web client and
Wt...").
Post by Nagaev Boris
But it is not how RESTful API should be implemented for Wt.
imho, you should use normal WApplication and connect
internalPathChanged() signal to handler function, that would create
WText("Hello");
In this case you'll get additional requests (application
initialization, javascript, etc).
And "Hello" would not be raw HTTP contents (as in 1.cpp), but a part of HTML.
Full example see attached file 2.cpp
Thanks for that suggestion. But I am looking for non-Wt clients to
access the resources exposed by Wt backend. I have detailed my
requirements on the Wt Help mailing list on Wt support website. You
can view my post and the ensuing discussion on that mailing list if
your are interested in knowing what I am trying to achieve with
RESTful services using Wt.

Thanks and regards,

~Plug

Loading...