Home > Generic HTTP Web Service (GHoWSt)
Introduction
Striving to be the C ABI of the Web platform.
GHoWSt is a multi-language, dynamic, native HTTP client and server RPC-style architecture free of schema, compilers, tooling, etc. Create a client in one line of code, call a remote method in the second line. Implement the service class, and its public interface is translated automatically to handle requests and display the service description for human or machine consumption. The Generic HTTP Web Service (GHoWSt) project maps native programming language semantics (methods/functions, arguments, return values, errors or exceptions) to and from basic HTTP requests in a generic, dynamic way based on convention. HTTP methods (GET, POST, PUT, PATCH, DELETE) are used to work with resources as usual, and subresources are used to implement custom methods that don't fit the standard HTTP methods.
The programmatic client uses any available dynamic proxy to translate class method calls to HTTP on the fly. In the case of C, the calling functions are written manually, but the library's invoker still does most of the lower level work. The Java client only needs an interface. The server maps the calls into the implementation automatically with an interface or equivalent. Visualizing it:
Motivation
GHoWSt is meant to require minimal effort for making Web service calls, leading to rapid prototyping. It is also designed for good production performance and works in browsers as well as servers. You can even use a plain HTML form with it, or more commonly, a rich client. The Java server translates the class interface to a human and machine-readable list of methods and parameters based on content negotiation at the root service URL to aid in service understanding. Where supported, annotations or the equivalent help document the service further. Additionally, OPTIONS requests are served automatically based on URI, to show a given resource's supported HTTP methods.
I made this for various reasons. Initially, it was to help me learn and practice a variety of languages and toolchains while making something potentially useful to a wider audience. But it turns out, members of my household and I have used it to do fun and silly networking stuff with whatever language, OS, and PC is available.
Technical details
-
Simplicity and broad compatibility
-
Objects can be sent through plain HTML forms with dot notation, JSON responses supported with no extra work.
- Allows basic usage by a browser and plain HTML, optionally enhanced with the JavaScript client to support more actions and less (or no) page reloading.
- Promotes simple API design and supports custom verbs in a semantic way.
- HTML responses can be added for any request, including from the service root, allowing the API to power an entire site to both browsers and to programmatic clients as well.
- Every dynamic client passes arguments using native language named arguments, so argument order isn't important. Java uses reflection on the interface and gets the names that way, translating to the correct method (with some minor constraints), while C requires some manual mapping.
-
Objects can be sent through plain HTML forms with dot notation, JSON responses supported with no extra work.
-
Native error handling
- Errors are returned as HTTP status codes, with details in a custom header.
- For supported languages, native runtime exceptions are thrown.
-
Service description
- Pass the ?ahttpi query parameter to the service root to get a list of all operations in either HTML or JSON.
- The appropriate metadata is provided to supply documentation in one place, suitable for use with the available GHoWSt clients, or for manually generating direct HTTP calls with any HTTP client.
-
Method name mapping and URI format avoids anti-patterns and promotes flexible convention
- Path parameters are avoided in favor of query parameters. Function over form. Native method names like
createResource()
ordeleteResource()
map to a GET or DELETE to /resource and the expected thing will happen. - For custom actions beyond CRUD operations, the URL format /resource/action is used, called natively by
actionResource()
. - More specifically, calling a client method
getRocket(id)
on a dynamic proxy would return a single rocket from a GET request,createRocket(new Rocket("ACME"))
would create one through a POST request, and you could also havelaunchRocket(id, new Fuel(), new Crew())
do something custom as well (it will get tunneled, or maybe even propelled, through a POST request). - Updates through PATCH, and "create or replace" operations through PUT are also covered.
- Path parameters are avoided in favor of query parameters. Function over form. Native method names like
Currently supported languages and their client and server GitHub repositories
- Client in C
- Client in Java
- Server in Java - serves a basic HTML client as well
- Client in Python
- Client in Ruby
- Client in PHP
- Client in JavaScript
Further information
- GitHub Weburg organization where you can explore many of the repositories mentioned
- Related project team and relevant repositories if you're interested in helping (requires a GitHub account and team membership)