{"id":1449,"date":"2020-06-03T09:21:02","date_gmt":"2020-06-03T09:21:02","guid":{"rendered":"https:\/\/smartfoxserver.com\/blog\/?p=1449"},"modified":"2020-06-03T09:21:02","modified_gmt":"2020-06-03T09:21:02","slug":"integrating-http-requests-in-sfs2x-extensions","status":"publish","type":"post","link":"https:\/\/smartfoxserver.com\/blog\/integrating-http-requests-in-sfs2x-extensions\/","title":{"rendered":"Integrating Http requests in SFS2X Extensions"},"content":{"rendered":"\n<p>The need to communicate between an Extension and a remote server via HTTP\/S is quite a common use case. Since SmartFoxServer already comes with embedded HTTP API we&#8217;re going to demonstrate how simple it is to integrate web requests in your server side code.<\/p>\n\n\n\n<!--more-->\n\n\n\n<h3>\u00bb Getting Started<\/h3>\n\n\n\n<p>Every SFS2X distribution comes with Apache&#8217;s <a href=\"https:\/\/hc.apache.org\/\">HttpComponent<\/a> libraries that provide a high level API for HTTP communication. The relative jar files are located under SFS2X\/lib\/ with these names:<\/p>\n\n\n\n<ul><li>httpclient-x.y.z.jar<\/li><li>httpcore-x.y.z.jar<\/li><\/ul>\n\n\n\n<p>The version numbers depend on the distribution of SFS2X and all you have to do is adding these two extra dependencies to your Extension project.<\/p>\n\n\n\n<p><strong>NOTE<\/strong>: if you&#8217;re new to developing server side code for SmartFoxServer we highly recommend this <a rel=\"noreferrer noopener\" aria-label=\"quick tutorial (opens in a new tab)\" href=\"http:\/\/docs2x.smartfoxserver.com\/ExtensionsJava\/writing-extensions\" target=\"_blank\">quick tutorial<\/a>, to get started.<\/p>\n\n\n\n<p>Let&#8217;s now take a look at a couple of examples to integrate the library in an SFS2X Extension.<\/p>\n\n\n\n<h3>\u00bb Example POST request<\/h3>\n\n\n<pre class=\"brush: java; title: ; notranslate\" title=\"\">\n@Override\npublic void init()\n{\n\tHttpClient httpclient = HttpClients.createDefault();\n\tHttpPost post = new HttpPost(&quot;http:\/\/my.domain.com\/page.php&quot;);\n\n\ttry \n\t{\n\t    List&amp;lt;NameValuePair&amp;gt; nameValuePairs = new ArrayList&amp;lt;NameValuePair&amp;gt;();\n\t    nameValuePairs.add(new BasicNameValuePair(&quot;Country&quot;,&quot;Greece&quot;));\n\t    nameValuePairs.add(new BasicNameValuePair(&quot;City&quot;,&quot;Athens&quot;));\n\t    \n\t    post.setEntity(new UrlEncodedFormEntity(nameValuePairs));\n\n\t    HttpResponse response = httpclient.execute(post);\n\t    BufferedReader rd = new BufferedReader(new InputStreamReader(response.getEntity().getContent()));\n\t    String line = &quot;&quot;;\n\t    \n\t    while ((line = rd.readLine()) != null) \n\t    {\n\t        System.out.println(line);\n\t    }\n\n\t} \n\tcatch (IOException e) \n\t{\n\t    e.printStackTrace();\n\t}\n}\n<\/pre>\n\n\n\n<p>At the top of our code we create an <strong>HttpClient<\/strong> object and we proceed with preparing the data we want to send. We&#8217;ll use the <strong>HttpPost<\/strong> class to wrap our key\/value parameters which are stored in a regular <strong>List<\/strong> as <strong>NameValuePair<\/strong> objects.<\/p>\n\n\n\n<p>Next, we proceed by <a rel=\"noreferrer noopener\" aria-label=\"url-encoding (opens in a new tab)\" href=\"https:\/\/en.wikipedia.org\/wiki\/Percent-encoding\" target=\"_blank\">url-encoding<\/a> the parameters and setting them as the entity of the <strong>HttpPost<\/strong> instance. Finally we send the request via the <strong>httpclient.execute()<\/strong> method and read the response through a <strong>BufferedReader<\/strong>.<\/p>\n\n\n\n<p>With this approach we&#8217;ll get back the HTML output sent by the server, so we will still need to be able to parse it correctly. A good approach to exchanging data between servers is to use JSON, rather than HTML which is a more document oriented markup.<\/p>\n\n\n\n<p>We could also use different approaches:<\/p>\n\n\n\n<ul><li>Send POST data (key\/value) and receive a JSON response<\/li><li>Send JSON data and receive a JSON response<\/li><\/ul>\n\n\n\n<p>Choosing which approach is best for you depends a lot on the use case, the complexity of the data being transferred and so on. Both are valid solutions.<\/p>\n\n\n\n<h3>\u00bb Example JSON request<\/h3>\n\n\n\n<p>Let&#8217;s now take a look at how to send and receive JSON data with a remote web server. For starters SmartFoxServer 2X already comes with a JSON coded library called <strong>json-lib-x.y.z.jar<\/strong> and found under the usual SFS2X\/lib\/ folder.<\/p>\n\n\n<pre class=\"brush: java; title: ; notranslate\" title=\"\">\n@Override\nprivate void init()\n{\n        HttpClient httpclient = HttpClients.createDefault();\n        CloseableHttpResponse response = null;\n\n        HttpPost httpPost = new HttpPost(&quot;http:\/\/my.domain.com\/page.php&quot;);\n\t\n        \/\/ Create JSON data to send\n        String jsonData = &quot;{'value':20}&quot;;\n        \n        StringEntity requestEntity = new StringEntity\n        (\n                jsonData,\n                ContentType.APPLICATION_JSON\n        );\n        \n        httpPost.setEntity(requestEntity);\n        HttpResponse rawResponse = (CloseableHttpResponse) httpclient.execute(httpPost);\n        \n        BufferedReader rd = new BufferedReader\n        (\n                new InputStreamReader(rawResponse.getEntity().getContent())\n        );\n        \n        StringBuffer response = new StringBuffer();\n        String line;\n        while ((line = rd.readLine()) != null) \n        {\n                response.append(line);\n        }\n\n        \/\/ Process Response\n        JSONObject jso = JSONObject.fromObject(jsonStr);\n}\n<\/pre>\n\n\n\n<p>The code is similar to the previous example. This time we also specify a different <em>ContentType<\/em> via the <strong>StringEntity<\/strong> class and then proceed with sending the request and reading back the response from the server.<\/p>\n\n\n\n<h3>\u00bb Performance Notes<\/h3>\n\n\n\n<p>The examples we have seen so far run <strong>synchronously<\/strong>, meaning that the current thread will block until the other side replies. This in turn means that if the remote server is laggy and we&#8217;re running many concurrent requests, we will end up with lots of waiting threads and ultimately poor scalability.<\/p>\n\n\n\n<p>To avoid these issues it is always better to minimize the number of concurrent HTTP calls and also to make sure that the web server is &#8220;as close as possible&#8221; to SmartFoxServer 2X. Ideally they should run in the same private network, which drastically reduces the lag between the two machines.<\/p>\n\n\n\n<p>Also, SmartFoxServer uses <a rel=\"noreferrer noopener\" aria-label=\"auto-load balancing thread pools (opens in a new tab)\" href=\"http:\/\/docs2x.smartfoxserver.com\/ExtensionsJava\/advanced-concepts#threadModel\" target=\"_blank\">auto-load balancing thread pools<\/a> so there&#8217;s no need to use custom threads or thread pools for HTTP calls. Only if your Extension makes heavy use of remote requests you will have to adjust the configuration accordingly.<\/p>\n\n\n\n<p>If you&#8217;re interested in learning more about threading and performance, we highly recommend <a rel=\"noreferrer noopener\" aria-label=\"this article from the blog (opens in a new tab)\" href=\"https:\/\/smartfoxserver.com\/blog\/sfs2x-multi-threading-demystified\/\" target=\"_blank\">this article from the blog<\/a>.<\/p>\n\n\n\n<h3>\u00bb Conclusion<\/h3>\n\n\n\n<p>Integrating HTTP calls in SFS2X Extensions is easily done since the necessary dependencies are already provided and thread management is automatic.<\/p>\n\n\n\n<p>If you have more questions or doubts make sure to join the conversation in our <a rel=\"noreferrer noopener\" href=\"https:\/\/www.smartfoxserver.com\/forums\/index.php\" target=\"_blank\">support forums<\/a> and let us know your feedback.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>The need to communicate between an Extension and a remote server via HTTP\/S is quite a common use case. Since SmartFoxServer already comes with embedded HTTP API we&#8217;re going to demonstrate how simple it is to integrate web requests in your server side code.<\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"closed","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":[],"categories":[1],"tags":[31,49,127,128,126],"_links":{"self":[{"href":"https:\/\/smartfoxserver.com\/blog\/wp-json\/wp\/v2\/posts\/1449"}],"collection":[{"href":"https:\/\/smartfoxserver.com\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/smartfoxserver.com\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/smartfoxserver.com\/blog\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/smartfoxserver.com\/blog\/wp-json\/wp\/v2\/comments?post=1449"}],"version-history":[{"count":19,"href":"https:\/\/smartfoxserver.com\/blog\/wp-json\/wp\/v2\/posts\/1449\/revisions"}],"predecessor-version":[{"id":1468,"href":"https:\/\/smartfoxserver.com\/blog\/wp-json\/wp\/v2\/posts\/1449\/revisions\/1468"}],"wp:attachment":[{"href":"https:\/\/smartfoxserver.com\/blog\/wp-json\/wp\/v2\/media?parent=1449"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/smartfoxserver.com\/blog\/wp-json\/wp\/v2\/categories?post=1449"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/smartfoxserver.com\/blog\/wp-json\/wp\/v2\/tags?post=1449"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}