{"id":129,"date":"2015-12-13T10:34:59","date_gmt":"2015-12-13T15:34:59","guid":{"rendered":"http:\/\/www.aradiogurl.net\/hhjournal\/?p=129"},"modified":"2015-12-13T10:37:48","modified_gmt":"2015-12-13T15:37:48","slug":"designing-an-api-server-part-1","status":"publish","type":"post","link":"https:\/\/www.aradiogurl.net\/hhjournal\/2015\/12\/13\/designing-an-api-server-part-1\/","title":{"rendered":"Designing an API Server &#8211; Part 1"},"content":{"rendered":"<p>Project: API Web Server<\/p>\n<p>I am currently building a simple Node.js based API web server. It&#8217;s primarily a proof-of-concept project that will be used when developing the API for another project. I have written similar servers for other projects in the past, this one should be cleaner and easier to use.<\/p>\n<p>At the core of the server is the node http2 module. This provides the HTTP\/2 web server, plus fall back to HTTP\/1.1 support. HTTP\/2 is the latest version of the hypertext transfer protocol and supports multiplexing data transfer connections, allowing multiple concurrent data streams. HTTP\/1.1 serializes data transfer, meaning one stream has finish before another can begin. Below is the code that instantiates the http2 server<\/p>\n<blockquote>\n<pre>\/\/Options for the http2 server\r\nconst httpServerOptions = {\r\n        key: fs.readFileSync(path.join(__dirname, 'keypath\/key.pem')),\r\n        cert: fs.readFileSync(path.join(__dirname, 'keypath\/cert.pem'))\r\n};\r\n\r\nvar http2server;\r\nif (process.env.HTTP2_PLAIN) {\r\n    console.log('Setting up HTTP2 Plain');\r\n    http2server = http2.raw.createServer({}, processRequest);\r\n} else {\r\n    console.log('Setting up HTTP2 TLS');\r\n    http2server = http2.createServer(httpServerOptions, processRequest);\r\n}\r\n<\/pre>\n<\/blockquote>\n<p>processRequest is the callback function that handles the server requests, it takes two objects as parameters, request and response.<\/p>\n<p><code>function processRequest(request, response) {<br \/>\n\/\/process the request and provide a response ...<\/code><\/p>\n<p>Since this is a simple server, it does not need to support many options. My current server implementation supports the following requirements:<\/p>\n<ul>\n<li>Passes GET and POST requests to the API endpoints<\/li>\n<li>API endpoints as modules<\/li>\n<li>Dynamically load modules during development<\/li>\n<li>Transfers html, js, css, and txt, files with correct mime types\n<ul>\n<li>The allows it to be used as a basic file web server<\/li>\n<\/ul>\n<\/li>\n<li>Display 404 when file or endpoint cannot be loaded<\/li>\n<li>Error logging<\/li>\n<\/ul>\n<p>This is not a complete web server, but it could eventually be. A complete web server would support multiple HTTP response codes, have a plugin infrastructure, support large numbers of mime types, access logging, and numerous other features. At this point it is good for development and is easy to expand.<\/p>\n<p>Since I have written similar servers in the past I looked at my previous code bases, it wasn&#8217;t pretty. I ended up finding duplicated code and signs of obvious confusion. When I coded the new server I made some similar mistakes, but upon reviewing the code I was able to move duplicated code into dedicated functions, then reworked the flow of the requests so that the main method was simpler. In the past I over complicated functions, stuffed too many actions into them. Simplify the methods increase the number of overall methods, but produced code that is easier to read and debug.<\/p>\n<p>I added dedicated methods for displaying 404 messages, writing content and its mime type back to the requester, and wrote a method dedicated to handling POST and GET requests.<\/p>\n<blockquote>\n<pre>function processRequestMethod (request) {\r\n  if (request.method === 'POST') {\r\n    var data='';\r\n    request.on('data', function(chunk) {\r\n      data += chunk;\r\n    });\r\n    request.on('end', function() {\r\n      return qs.parse(data);\r\n    });\r\n    request.on('error', function(e) {\r\n      console.error('ERROR with POST request '+e.message);\r\n    });\r\n  } else {\r\n  \/\/Process as GET\r\n    return qs.parse(url.parse(request.url).query);\r\n  }\r\n}\r\n<\/pre>\n<\/blockquote>\n<p>My Next goal was to dynamically load API modules, to be continued in part 2.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>Project: API Web Server I am currently building a simple Node.js based API web server. It&#8217;s primarily a proof-of-concept project that will be used when developing the API for another project. I have written similar servers for other projects in the past, this one should be cleaner and easier to use. At the core of [&hellip;]<\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[10],"tags":[23,24,16],"class_list":["post-129","post","type-post","status-publish","format-standard","hentry","category-deveng","tag-apiserver","tag-project","tag-software-development"],"_links":{"self":[{"href":"https:\/\/www.aradiogurl.net\/hhjournal\/wp-json\/wp\/v2\/posts\/129","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/www.aradiogurl.net\/hhjournal\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.aradiogurl.net\/hhjournal\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.aradiogurl.net\/hhjournal\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/www.aradiogurl.net\/hhjournal\/wp-json\/wp\/v2\/comments?post=129"}],"version-history":[{"count":4,"href":"https:\/\/www.aradiogurl.net\/hhjournal\/wp-json\/wp\/v2\/posts\/129\/revisions"}],"predecessor-version":[{"id":136,"href":"https:\/\/www.aradiogurl.net\/hhjournal\/wp-json\/wp\/v2\/posts\/129\/revisions\/136"}],"wp:attachment":[{"href":"https:\/\/www.aradiogurl.net\/hhjournal\/wp-json\/wp\/v2\/media?parent=129"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.aradiogurl.net\/hhjournal\/wp-json\/wp\/v2\/categories?post=129"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.aradiogurl.net\/hhjournal\/wp-json\/wp\/v2\/tags?post=129"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}