{"id":3147,"date":"2021-01-02T14:12:14","date_gmt":"2021-01-02T06:12:14","guid":{"rendered":"http:\/\/blog.coolcoding.cn\/?p=3147"},"modified":"2021-01-02T19:42:05","modified_gmt":"2021-01-02T11:42:05","slug":"http-api-downloading-webpages-using-web-requests","status":"publish","type":"post","link":"https:\/\/blog.coolcoding.cn\/?p=3147","title":{"rendered":"HTTP API \u2013 downloading webpages using web requests"},"content":{"rendered":"\n<p> When you&#8217;re maintaining scoreboards or other such things that require regular HTTP request access to servers, you can use the HTTP API to perform such web request tasks. <\/p>\n\n\n\n<h1 class=\"wp-block-heading\">Getting ready<\/h1>\n\n\n\n<p>Have a server that you&#8217;re allowed to request data via HTTP from. You can use a public server of any type to try out HTTP requests, if you&#8217;d like.<\/p>\n\n\n\n<h1 class=\"wp-block-heading\">How to do it&#8230;<\/h1>\n\n\n\n<ol><li>Link to the&nbsp;HTTP&nbsp;API in your&nbsp;ProjectName.Build.cs&nbsp;file:<\/li><\/ol>\n\n\n\n<pre class=\"wp-block-preformatted\">using UnrealBuildTool;<br><br>public class Chapter_11 : ModuleRules<br>{<br>    public Chapter_11(ReadOnlyTargetRules Target) : base(Target)<br>    {<br>        PCHUsage = PCHUsageMode.UseExplicitOrSharedPCHs;<br>    <br>        PublicDependencyModuleNames.AddRange(new string[] {<br>        \"Core\", \"CoreUObject\", \"Engine\", \"InputCore\" });<br>        PublicDependencyModuleNames.AddRange(new string[] { <br>        \"GameplayAbilities\", \"GameplayTags\", \"GameplayTasks\" });<br><strong>        PublicDependencyModuleNames.AddRange(new string[] {<br>        \"HTTP\" });<\/strong><br><br>        PrivateDependencyModuleNames.AddRange(new string[] { });<br><br>        \/\/ Uncomment if you are using Slate UI<br>        \/\/ PrivateDependencyModuleNames.AddRange(new string[]<br>        \/\/ { \"Slate\", \"SlateCore\" });<br>        <br>        \/\/ Uncomment if you are using online features<br>        \/\/ PrivateDependencyModuleNames.Add(\"OnlineSubsystem\");<br><br>        \/\/ To include OnlineSubsystemSteam, add it to the plugins section in your uproject file with the Enabled attribute set to true<br>    }<br>}<\/pre>\n\n\n\n<ol><li>In the file that you will send your web request from (in my case, I&#8217;ll be using the&nbsp;Chapter_11GameModeBase&nbsp;class), include the new additions to the following code snippet:<\/li><\/ol>\n\n\n\n<pre class=\"wp-block-preformatted\">#pragma once<br><br>#include \"CoreMinimal.h\"<br>#include \"GameFramework\/GameModeBase.h\"<br><strong>#include \"Runtime\/Online\/HTTP\/Public\/HttpManager.h\" <\/strong><br><strong>#include \"Runtime\/Online\/HTTP\/Public\/HttpModule.h\" <\/strong><br><strong>#include \"Runtime\/Online\/HTTP\/Public\/HttpRetrySystem.h\"<\/strong> <br><strong>#include \"Runtime\/Online\/HTTP\/Public\/Interfaces\/IHttpResponse.h\"<\/strong><br><strong>using namespace FHttpRetrySystem;<\/strong><br>#include \"Chapter_11GameModeBase.generated.h\"<\/pre>\n\n\n\n<ol><li>Construct an&nbsp;IHttpRequest&nbsp;object from&nbsp;FHttpModule&nbsp;using the following code:<\/li><\/ol>\n\n\n\n<pre class=\"wp-block-preformatted\">TSharedRef&lt;IHttpRequest&gt; <br> http=FHttpModule::Get().CreateRequest();<\/pre>\n\n\n\n<p>FHttpModule&nbsp;is a singleton object. One copy of it exists for the entire program that you are meant to use for all interactions with the&nbsp;FHttpModule&nbsp;class.<\/p>\n\n\n\n<ol><li>Attach your function to run to the&nbsp;IHttpRequest&nbsp;object&#8217;s&nbsp;FHttpRequestCompleteDelegate, which has the following signature:<\/li><\/ol>\n\n\n\n<pre class=\"wp-block-preformatted\">void HttpRequestComplete( FHttpRequestPtr request,<br> FHttpResponsePtr response, bool success );<\/pre>\n\n\n\n<ol><li>The delegate is found inside of the&nbsp;IHttpRequest&nbsp;object as&nbsp;http-&gt;OnProcessRequestComplete():<\/li><\/ol>\n\n\n\n<pre class=\"wp-block-preformatted\">FHttpRequestCompleteDelegate&amp; delegate = http-<br> &gt;OnProcessRequestComplete();<\/pre>\n\n\n\n<p>There are a few ways to attach a callback function to the delegate. You can use the following methods:<\/p>\n\n\n\n<ul><li>A lambda using&nbsp;delegate.BindLambda():<\/li><\/ul>\n\n\n\n<pre class=\"wp-block-preformatted\">delegate.BindLambda( \n  \/\/ Anonymous, inlined code function (aka lambda) \n  []( FHttpRequestPtr request, FHttpResponsePtr response, bool <br>   success ) -&gt; void \n{ \n  UE_LOG( LogTemp, Warning, TEXT( \"Http Response: %d, %s\" ), \n  request-&gt;GetResponse()-&gt;GetResponseCode(), \n  *request-&gt;GetResponse()-&gt;GetContentAsString() ); \n}); <\/pre>\n\n\n\n<ol><li>Specify the URL of the site you&#8217;d like to hit:<\/li><\/ol>\n\n\n\n<pre class=\"wp-block-preformatted\">http-&gt;SetURL( TEXT( \"http:\/\/unrealengine.com\" ) ); <\/pre>\n\n\n\n<ol><li>Process the request by calling&nbsp;ProcessRequest:<\/li><\/ol>\n\n\n\n<pre class=\"wp-block-preformatted\">http-&gt;ProcessRequest();<\/pre>\n\n\n\n<p>Then, when you run this code, you should notice the contents of the URL you pointed to being displayed:<\/p>\n\n\n\n<figure class=\"wp-block-image\"><img decoding=\"async\" src=\"http:\/\/blog.coolcoding.cn\/wp-content\/uploads\/2021\/01\/b5de988c-e6c7-4509-a9af-9ff2c3a41881.png\" alt=\"\"\/><\/figure>\n\n\n\n<p>HTML content of unrealengine.com displayed<\/p>\n\n\n\n<p>Of course, in this instance, it&#8217;s a web page, but you can easily point this to a CSV file, text document, or anything to obtain information for your project!<\/p>\n\n\n\n<h1 class=\"wp-block-heading\">How it works&#8230;<\/h1>\n\n\n\n<p>The HTTP object is all you need to send off HTTP requests to a server and get HTTP responses. You can use the HTTP request\/response for anything that you wish; for example, submitting scores to a high scores table or to retrieve text to display in-game from a server.<\/p>\n\n\n\n<p>They are decked out with a URL to visit and a function callback to run when the request is complete. Finally, they are sent off via&nbsp;FManager. When the web server responds, your callback is called and the results of your HTTP response can be shown.<\/p>\n\n\n\n<h1 class=\"wp-block-heading\">There&#8217;s more&#8230;<\/h1>\n\n\n\n<p>There are also other ways in which you can attach a callback function to the delegate:<\/p>\n\n\n\n<ul><li>Using any UObject&#8217;s member function:<\/li><\/ul>\n\n\n\n<pre class=\"wp-block-preformatted\">delegate.BindUObject(this, &amp;AChapter_11GameModeBase::HttpRequestComplete);<\/pre>\n\n\n\n<p>You cannot attach to&nbsp;UFunction&nbsp;directly here as the&nbsp;.BindUFunction()&nbsp;command requests arguments that are all&nbsp;UCLASS,&nbsp;USTRUCT,&nbsp;or&nbsp;UENUM.<\/p>\n\n\n\n<ul><li>With any plain old C++ object&#8217;s member function, using&nbsp;.BindRaw:<\/li><\/ul>\n\n\n\n<pre class=\"wp-block-preformatted\">PlainObject* plainObject = new PlainObject();<br>delegate.BindRaw( plainObject, &amp;PlainObject::httpHandler );<br> \/\/ plainObject cannot be DELETED Until httpHandler gets<br> \/\/ called..<\/pre>\n\n\n\n<p>You have to ensure that your&nbsp;plainObject&nbsp;refers to a valid object in memory at the time that the HTTP request completes. This means that you cannot use&nbsp;TAutoPtr&nbsp;on&nbsp;plainObject, because that will deallocate&nbsp;plainObject&nbsp;at the end of the block in which it is declared, but that may be before the HTTP request completes.<\/p>\n\n\n\n<ul><li>Using a global C-style static function:<\/li><\/ul>\n\n\n\n<pre class=\"wp-block-preformatted\">\/\/ C-style function for handling the HTTP response: \nvoid httpHandler( FHttpRequestPtr request,  \nFHttpResponsePtr response, bool success ) \n{ \n  Info( \"static: Http req handled\" ); \n} \ndelegate.BindStatic( &amp;httpHandler ); <\/pre>\n\n\n\n<p>When using a delegate callback with an object, be sure that the object instance that you&#8217;re calling back on lives on at least until the point at which the&nbsp;HttpResponse&nbsp;arrives back from the server. Processing the&nbsp;HttpRequest&nbsp;takes real time to run. It is a web request after all\u2014think of waiting for a web page to load.<\/p>\n\n\n\n<p>You have to be sure that the object instance on which you&#8217;re calling the callback function has not deallocated on you between the time of the initial call and the invocation of your&nbsp;HttpHandler&nbsp;function. The object must still be in memory when the callback returns after the HTTP request completes.<\/p>\n\n\n\n<p>You cannot simply expect that the&nbsp;HttpResponse&nbsp;function happens immediately after you attach the callback function and call&nbsp;ProcessRequest()! Using a reference counted&nbsp;UObject&nbsp;instance to attach the&nbsp;HttpHandler&nbsp;member function is a good idea to ensure that the object stays in memory until the HTTP request completes.<\/p>\n\n\n\n<p>You can see an example of all seven possible ways it can be used inside of the&nbsp;Chapter_11GameModeBase.cpp&nbsp;file in the Example Code for this chapter.<\/p>\n\n\n\n<p>You can set additional HTTP request parameters via the following member functions:<\/p>\n\n\n\n<ul><li>SetVerb(), to change whether you are using the&nbsp;GET&nbsp;or&nbsp;POST&nbsp;method in your&nbsp;HTTP request<\/li><li>SetHeaders(), to modify any general header settings you would like<\/li><\/ul>\n","protected":false},"excerpt":{"rendered":"<p>When you&#8217;re maintaining scoreboards or other such [&hellip;]<\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"closed","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[27,1],"tags":[],"_links":{"self":[{"href":"https:\/\/blog.coolcoding.cn\/index.php?rest_route=\/wp\/v2\/posts\/3147"}],"collection":[{"href":"https:\/\/blog.coolcoding.cn\/index.php?rest_route=\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/blog.coolcoding.cn\/index.php?rest_route=\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/blog.coolcoding.cn\/index.php?rest_route=\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/blog.coolcoding.cn\/index.php?rest_route=%2Fwp%2Fv2%2Fcomments&post=3147"}],"version-history":[{"count":1,"href":"https:\/\/blog.coolcoding.cn\/index.php?rest_route=\/wp\/v2\/posts\/3147\/revisions"}],"predecessor-version":[{"id":3152,"href":"https:\/\/blog.coolcoding.cn\/index.php?rest_route=\/wp\/v2\/posts\/3147\/revisions\/3152"}],"wp:attachment":[{"href":"https:\/\/blog.coolcoding.cn\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=3147"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/blog.coolcoding.cn\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=3147"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/blog.coolcoding.cn\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=3147"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}