{"id":562,"date":"2017-03-06T12:41:00","date_gmt":"2017-03-06T12:41:00","guid":{"rendered":"https:\/\/blogs.zeiss.com\/digital-innovation\/en\/?p=562"},"modified":"2020-06-05T12:54:38","modified_gmt":"2020-06-05T12:54:38","slug":"hal-hypermedia-api","status":"publish","type":"post","link":"https:\/\/blogs.zeiss.com\/digital-innovation\/en\/hal-hypermedia-api\/","title":{"rendered":"Using a HAL hypermedia API in an Angular App"},"content":{"rendered":"\n<p>Modern APIs are often realized in a RESTful way. Besides being stateless and using the correct HTTP verbs for specific actions, REST does not specify the response of a request. <a href=\"https:\/\/sookocheff.com\/post\/api\/on-choosing-a-hypermedia-format\" target=\"_blank\" rel=\"noreferrer noopener\">Hypermedia Formats<\/a>&nbsp;are trying to overcome this issue by providing a discoverable API. <a href=\"http:\/\/stateless.co\/hal_specification.html\" target=\"_blank\" rel=\"noreferrer noopener\">Hypermedia Application Language<\/a>&nbsp;is one format and abbreviates as HAL.<\/p>\n\n\n\n<p>HAL is a set of conventions expressing hyperlinks in either JSON or XML. Resources returned by a HAL API contain a <code>_links<\/code> element hosting a self link and a link to resources. This makes HAL APIs discoverable as it is possible to navigate from one resource to another via the links provided within the resources knowing only a single entry point. This article describes how to use HAL hypermedia APIs in Angular.<\/p>\n\n\n\n<p>Consuming a HAL API in an Angular app is pretty straight forward. Just use the Angular <code>http<\/code> API as you would for a http request.<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>private restQuery(): Observable&lt;HypermediaResult> {\n  return this.http.get('api-endpoint') \/\/ URI to the API\n    .map(response => response.json() || new HypermediaResult())\n    .share();\n }<\/code><\/pre>\n\n\n\n<p>As abstraction for all API responses we introduced the <code>HypermediaResult<\/code> class containing a <code>_links<\/code> element which acts as host for the self link and an array of links to resources.<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>export class HypermediaResult {\n  _links: {\n    self: {\n      href: string\n    },\n    &#91;s: string]: {\n      href: string\n    }\n  };\n}<\/code><\/pre>\n\n\n\n<p>We implemented a HAL API with JSON. As explained previous the response contains a self link and a link to a resource. In this particular case the <code>leads<\/code> resource.<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>{ \"_links\" : {\n  \"self\" : {\n    \"href\" : \"http:\/\/www.clintr.com\/api\/search\/\"\n  },\n  \"leads\" : {\n    \"href\" : \"http:\/\/www.clintr.com\/api\/search\/companies\/leads{?query}\"\n}}}<\/code><\/pre>\n\n\n\n<p>To specify query parameters HAL makes use of templated URIs. The <code>leads<\/code> resource provides a query parameter named <code>query<\/code>. This makes query parameters transparent in the API. Leads could be retrieved by following request:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>searchLeads(searchstring: string): Observable&lt;HypermediaResult> {\n  return this.restQuery().flatMap((hypermediaResult: HypermediaResult) => {\n    let link = uriTemplates(hypermediaResult._links&#91;'leads'].href).fill({'query': searchString});\n    return this.http.get(link);\n    })\n    .catch(this.handleError)\n    .map(res => res.json() || new HypermediaResult());\n}<\/code><\/pre>\n\n\n\n<p>As you might have noticed we are using the <a href=\"https:\/\/github.com\/geraintluff\/uri-templates\" target=\"_blank\" rel=\"noreferrer noopener\">URI-Templates<\/a> project instead of <code>UrlSearchParams<\/code> from the Angular http API. <code>UrlSearchParams<\/code> is not capable of handling templated URIs.<\/p>\n\n\n\n<p>A pretty young project is <a href=\"https:\/\/github.com\/dherges\/ng-hal\" target=\"_blank\" rel=\"noreferrer noopener\"><code>ng-hal<\/code><\/a> combining the Angular http API, URI-Templates and halfred providing a Navigator concept similar to Angular http and a shortcut for the observables. At the time of writing this project was not ready to use.<\/p>\n\n\n\n<p>The <code>http<\/code> library from Angular does not have a support of&nbsp;templated URLs out of the box, but they are required to make query parameters transparent in API definitions. For future releases of Angular it would be great to have native support of templated URLs. So far they are not on the roadmap. Maybe future releases of <code>ng-hal<\/code> close this gap. For now using Angular and the URI-Templates lib is an easy solution to consume HAL APIs.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>Modern APIs are often realized in a RESTful way. Hypermedia Formats are trying to overcome this issue by providing a discoverable API. Hypermedia Application Language is one format and abbreviates as HAL.<\/p>\n","protected":false},"author":73,"featured_media":564,"comment_status":"closed","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"_acf_changed":false,"advgb_blocks_editor_width":"","advgb_blocks_columns_visual_guide":"","footnotes":""},"categories":[8],"tags":[289,290,291,292,293,261,286],"topics":[],"class_list":["post-562","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-web","tag-apis","tag-rest","tag-hal","tag-hypermedia-application-language","tag-hypermedia","tag-angular","tag-angular-app"],"acf":[],"yoast_head":"<!-- This site is optimized with the Yoast SEO plugin v24.0 - https:\/\/yoast.com\/wordpress\/plugins\/seo\/ -->\n<title>HAL hypermedia API in an Angular App - ZEISS Digital Innovation Blog<\/title>\n<meta name=\"description\" content=\"Modern APIs are often realized in a RESTful way. Hypermedia Formats are trying to overcome this issue by providing a discoverable API.\" \/>\n<meta name=\"robots\" content=\"index, follow, max-snippet:-1, max-image-preview:large, max-video-preview:-1\" \/>\n<link rel=\"canonical\" href=\"https:\/\/blogs.zeiss.com\/digital-innovation\/en\/hal-hypermedia-api\/\" \/>\n<meta property=\"og:locale\" content=\"en_US\" \/>\n<meta property=\"og:type\" content=\"article\" \/>\n<meta property=\"og:title\" content=\"HAL hypermedia API in an Angular App - ZEISS Digital Innovation Blog\" \/>\n<meta property=\"og:description\" content=\"Modern APIs are often realized in a RESTful way. Hypermedia Formats are trying to overcome this issue by providing a discoverable API.\" \/>\n<meta property=\"og:url\" content=\"https:\/\/blogs.zeiss.com\/digital-innovation\/en\/hal-hypermedia-api\/\" \/>\n<meta property=\"og:site_name\" content=\"Digital Innovation Blog\" \/>\n<meta property=\"article:published_time\" content=\"2017-03-06T12:41:00+00:00\" \/>\n<meta property=\"article:modified_time\" content=\"2020-06-05T12:54:38+00:00\" \/>\n<meta property=\"og:image\" content=\"https:\/\/blogs.zeiss.com\/digital-innovation\/en\/wp-content\/uploads\/sites\/3\/2017\/03\/201703_hal_api_fi.png\" \/>\n\t<meta property=\"og:image:width\" content=\"1281\" \/>\n\t<meta property=\"og:image:height\" content=\"734\" \/>\n\t<meta property=\"og:image:type\" content=\"image\/png\" \/>\n<meta name=\"author\" content=\"Matthias Baumgart\" \/>\n<meta name=\"twitter:card\" content=\"summary_large_image\" \/>\n<meta name=\"twitter:label1\" content=\"Written by\" \/>\n\t<meta name=\"twitter:data1\" content=\"Matthias Baumgart\" \/>\n\t<meta name=\"twitter:label2\" content=\"Est. reading time\" \/>\n\t<meta name=\"twitter:data2\" content=\"2 minutes\" \/>\n<script type=\"application\/ld+json\" class=\"yoast-schema-graph\">{\"@context\":\"https:\/\/schema.org\",\"@graph\":[{\"@type\":\"WebPage\",\"@id\":\"https:\/\/blogs.zeiss.com\/digital-innovation\/en\/hal-hypermedia-api\/\",\"url\":\"https:\/\/blogs.zeiss.com\/digital-innovation\/en\/hal-hypermedia-api\/\",\"name\":\"HAL hypermedia API in an Angular App - ZEISS Digital Innovation Blog\",\"isPartOf\":{\"@id\":\"https:\/\/blogs.zeiss.com\/digital-innovation\/en\/#website\"},\"primaryImageOfPage\":{\"@id\":\"https:\/\/blogs.zeiss.com\/digital-innovation\/en\/hal-hypermedia-api\/#primaryimage\"},\"image\":{\"@id\":\"https:\/\/blogs.zeiss.com\/digital-innovation\/en\/hal-hypermedia-api\/#primaryimage\"},\"thumbnailUrl\":\"https:\/\/blogs.zeiss.com\/digital-innovation\/en\/wp-content\/uploads\/sites\/3\/2017\/03\/201703_hal_api_fi.png\",\"datePublished\":\"2017-03-06T12:41:00+00:00\",\"dateModified\":\"2020-06-05T12:54:38+00:00\",\"author\":{\"@id\":\"https:\/\/blogs.zeiss.com\/digital-innovation\/en\/#\/schema\/person\/cbc7c69ddcc2e0040b341c88ea822f70\"},\"description\":\"Modern APIs are often realized in a RESTful way. Hypermedia Formats are trying to overcome this issue by providing a discoverable API.\",\"breadcrumb\":{\"@id\":\"https:\/\/blogs.zeiss.com\/digital-innovation\/en\/hal-hypermedia-api\/#breadcrumb\"},\"inLanguage\":\"en-US\",\"potentialAction\":[{\"@type\":\"ReadAction\",\"target\":[\"https:\/\/blogs.zeiss.com\/digital-innovation\/en\/hal-hypermedia-api\/\"]}]},{\"@type\":\"ImageObject\",\"inLanguage\":\"en-US\",\"@id\":\"https:\/\/blogs.zeiss.com\/digital-innovation\/en\/hal-hypermedia-api\/#primaryimage\",\"url\":\"https:\/\/blogs.zeiss.com\/digital-innovation\/en\/wp-content\/uploads\/sites\/3\/2017\/03\/201703_hal_api_fi.png\",\"contentUrl\":\"https:\/\/blogs.zeiss.com\/digital-innovation\/en\/wp-content\/uploads\/sites\/3\/2017\/03\/201703_hal_api_fi.png\",\"width\":1281,\"height\":734},{\"@type\":\"BreadcrumbList\",\"@id\":\"https:\/\/blogs.zeiss.com\/digital-innovation\/en\/hal-hypermedia-api\/#breadcrumb\",\"itemListElement\":[{\"@type\":\"ListItem\",\"position\":1,\"name\":\"Home\",\"item\":\"https:\/\/blogs.zeiss.com\/digital-innovation\/en\/\"},{\"@type\":\"ListItem\",\"position\":2,\"name\":\"Using a HAL hypermedia API in an Angular App\"}]},{\"@type\":\"WebSite\",\"@id\":\"https:\/\/blogs.zeiss.com\/digital-innovation\/en\/#website\",\"url\":\"https:\/\/blogs.zeiss.com\/digital-innovation\/en\/\",\"name\":\"Digital Innovation Blog\",\"description\":\"\",\"potentialAction\":[{\"@type\":\"SearchAction\",\"target\":{\"@type\":\"EntryPoint\",\"urlTemplate\":\"https:\/\/blogs.zeiss.com\/digital-innovation\/en\/?s={search_term_string}\"},\"query-input\":{\"@type\":\"PropertyValueSpecification\",\"valueRequired\":true,\"valueName\":\"search_term_string\"}}],\"inLanguage\":\"en-US\"},{\"@type\":\"Person\",\"@id\":\"https:\/\/blogs.zeiss.com\/digital-innovation\/en\/#\/schema\/person\/cbc7c69ddcc2e0040b341c88ea822f70\",\"name\":\"Matthias Baumgart\",\"image\":{\"@type\":\"ImageObject\",\"inLanguage\":\"en-US\",\"@id\":\"https:\/\/blogs.zeiss.com\/digital-innovation\/en\/#\/schema\/person\/image\/\",\"url\":\"https:\/\/blogs.zeiss.com\/digital-innovation\/en\/wp-content\/uploads\/sites\/3\/2020\/05\/baumgart_matthias-1-150x150.jpg\",\"contentUrl\":\"https:\/\/blogs.zeiss.com\/digital-innovation\/en\/wp-content\/uploads\/sites\/3\/2020\/05\/baumgart_matthias-1-150x150.jpg\",\"caption\":\"Matthias Baumgart\"},\"description\":\"Matthias works as a Senior Software Engineer at ZEISS Digital Innovation in Dresden, Germany. As full stack developer he loves creating web applications. Currently he works on modern web applications with Angular and microservices.\",\"url\":\"https:\/\/blogs.zeiss.com\/digital-innovation\/en\/author\/enmatthiasbaumgart\/\"}]}<\/script>\n<!-- \/ Yoast SEO plugin. -->","yoast_head_json":{"title":"HAL hypermedia API in an Angular App - ZEISS Digital Innovation Blog","description":"Modern APIs are often realized in a RESTful way. Hypermedia Formats are trying to overcome this issue by providing a discoverable API.","robots":{"index":"index","follow":"follow","max-snippet":"max-snippet:-1","max-image-preview":"max-image-preview:large","max-video-preview":"max-video-preview:-1"},"canonical":"https:\/\/blogs.zeiss.com\/digital-innovation\/en\/hal-hypermedia-api\/","og_locale":"en_US","og_type":"article","og_title":"HAL hypermedia API in an Angular App - ZEISS Digital Innovation Blog","og_description":"Modern APIs are often realized in a RESTful way. Hypermedia Formats are trying to overcome this issue by providing a discoverable API.","og_url":"https:\/\/blogs.zeiss.com\/digital-innovation\/en\/hal-hypermedia-api\/","og_site_name":"Digital Innovation Blog","article_published_time":"2017-03-06T12:41:00+00:00","article_modified_time":"2020-06-05T12:54:38+00:00","og_image":[{"width":1281,"height":734,"url":"https:\/\/blogs.zeiss.com\/digital-innovation\/en\/wp-content\/uploads\/sites\/3\/2017\/03\/201703_hal_api_fi.png","type":"image\/png"}],"author":"Matthias Baumgart","twitter_card":"summary_large_image","twitter_misc":{"Written by":"Matthias Baumgart","Est. reading time":"2 minutes"},"schema":{"@context":"https:\/\/schema.org","@graph":[{"@type":"WebPage","@id":"https:\/\/blogs.zeiss.com\/digital-innovation\/en\/hal-hypermedia-api\/","url":"https:\/\/blogs.zeiss.com\/digital-innovation\/en\/hal-hypermedia-api\/","name":"HAL hypermedia API in an Angular App - ZEISS Digital Innovation Blog","isPartOf":{"@id":"https:\/\/blogs.zeiss.com\/digital-innovation\/en\/#website"},"primaryImageOfPage":{"@id":"https:\/\/blogs.zeiss.com\/digital-innovation\/en\/hal-hypermedia-api\/#primaryimage"},"image":{"@id":"https:\/\/blogs.zeiss.com\/digital-innovation\/en\/hal-hypermedia-api\/#primaryimage"},"thumbnailUrl":"https:\/\/blogs.zeiss.com\/digital-innovation\/en\/wp-content\/uploads\/sites\/3\/2017\/03\/201703_hal_api_fi.png","datePublished":"2017-03-06T12:41:00+00:00","dateModified":"2020-06-05T12:54:38+00:00","author":{"@id":"https:\/\/blogs.zeiss.com\/digital-innovation\/en\/#\/schema\/person\/cbc7c69ddcc2e0040b341c88ea822f70"},"description":"Modern APIs are often realized in a RESTful way. Hypermedia Formats are trying to overcome this issue by providing a discoverable API.","breadcrumb":{"@id":"https:\/\/blogs.zeiss.com\/digital-innovation\/en\/hal-hypermedia-api\/#breadcrumb"},"inLanguage":"en-US","potentialAction":[{"@type":"ReadAction","target":["https:\/\/blogs.zeiss.com\/digital-innovation\/en\/hal-hypermedia-api\/"]}]},{"@type":"ImageObject","inLanguage":"en-US","@id":"https:\/\/blogs.zeiss.com\/digital-innovation\/en\/hal-hypermedia-api\/#primaryimage","url":"https:\/\/blogs.zeiss.com\/digital-innovation\/en\/wp-content\/uploads\/sites\/3\/2017\/03\/201703_hal_api_fi.png","contentUrl":"https:\/\/blogs.zeiss.com\/digital-innovation\/en\/wp-content\/uploads\/sites\/3\/2017\/03\/201703_hal_api_fi.png","width":1281,"height":734},{"@type":"BreadcrumbList","@id":"https:\/\/blogs.zeiss.com\/digital-innovation\/en\/hal-hypermedia-api\/#breadcrumb","itemListElement":[{"@type":"ListItem","position":1,"name":"Home","item":"https:\/\/blogs.zeiss.com\/digital-innovation\/en\/"},{"@type":"ListItem","position":2,"name":"Using a HAL hypermedia API in an Angular App"}]},{"@type":"WebSite","@id":"https:\/\/blogs.zeiss.com\/digital-innovation\/en\/#website","url":"https:\/\/blogs.zeiss.com\/digital-innovation\/en\/","name":"Digital Innovation Blog","description":"","potentialAction":[{"@type":"SearchAction","target":{"@type":"EntryPoint","urlTemplate":"https:\/\/blogs.zeiss.com\/digital-innovation\/en\/?s={search_term_string}"},"query-input":{"@type":"PropertyValueSpecification","valueRequired":true,"valueName":"search_term_string"}}],"inLanguage":"en-US"},{"@type":"Person","@id":"https:\/\/blogs.zeiss.com\/digital-innovation\/en\/#\/schema\/person\/cbc7c69ddcc2e0040b341c88ea822f70","name":"Matthias Baumgart","image":{"@type":"ImageObject","inLanguage":"en-US","@id":"https:\/\/blogs.zeiss.com\/digital-innovation\/en\/#\/schema\/person\/image\/","url":"https:\/\/blogs.zeiss.com\/digital-innovation\/en\/wp-content\/uploads\/sites\/3\/2020\/05\/baumgart_matthias-1-150x150.jpg","contentUrl":"https:\/\/blogs.zeiss.com\/digital-innovation\/en\/wp-content\/uploads\/sites\/3\/2020\/05\/baumgart_matthias-1-150x150.jpg","caption":"Matthias Baumgart"},"description":"Matthias works as a Senior Software Engineer at ZEISS Digital Innovation in Dresden, Germany. As full stack developer he loves creating web applications. Currently he works on modern web applications with Angular and microservices.","url":"https:\/\/blogs.zeiss.com\/digital-innovation\/en\/author\/enmatthiasbaumgart\/"}]}},"author_meta":{"display_name":"Matthias Baumgart","author_link":"https:\/\/blogs.zeiss.com\/digital-innovation\/en\/author\/enmatthiasbaumgart\/"},"featured_img":"https:\/\/blogs.zeiss.com\/digital-innovation\/en\/wp-content\/uploads\/sites\/3\/2017\/03\/201703_hal_api_fi-600x344.png","coauthors":[],"tax_additional":{"categories":{"linked":["<a href=\"https:\/\/blogs.zeiss.com\/digital-innovation\/en\/category\/web\/\" class=\"advgb-post-tax-term\">Web<\/a>"],"unlinked":["<span class=\"advgb-post-tax-term\">Web<\/span>"]},"tags":{"linked":["<a href=\"https:\/\/blogs.zeiss.com\/digital-innovation\/en\/category\/web\/\" class=\"advgb-post-tax-term\">APIs<\/a>","<a href=\"https:\/\/blogs.zeiss.com\/digital-innovation\/en\/category\/web\/\" class=\"advgb-post-tax-term\">REST<\/a>","<a href=\"https:\/\/blogs.zeiss.com\/digital-innovation\/en\/category\/web\/\" class=\"advgb-post-tax-term\">HAL<\/a>","<a href=\"https:\/\/blogs.zeiss.com\/digital-innovation\/en\/category\/web\/\" class=\"advgb-post-tax-term\">Hypermedia Application Language<\/a>","<a href=\"https:\/\/blogs.zeiss.com\/digital-innovation\/en\/category\/web\/\" class=\"advgb-post-tax-term\">Hypermedia<\/a>","<a href=\"https:\/\/blogs.zeiss.com\/digital-innovation\/en\/category\/web\/\" class=\"advgb-post-tax-term\">Angular<\/a>","<a href=\"https:\/\/blogs.zeiss.com\/digital-innovation\/en\/category\/web\/\" class=\"advgb-post-tax-term\">Angular App<\/a>"],"unlinked":["<span class=\"advgb-post-tax-term\">APIs<\/span>","<span class=\"advgb-post-tax-term\">REST<\/span>","<span class=\"advgb-post-tax-term\">HAL<\/span>","<span class=\"advgb-post-tax-term\">Hypermedia Application Language<\/span>","<span class=\"advgb-post-tax-term\">Hypermedia<\/span>","<span class=\"advgb-post-tax-term\">Angular<\/span>","<span class=\"advgb-post-tax-term\">Angular App<\/span>"]}},"comment_count":"0","relative_dates":{"created":"Posted 9 years ago","modified":"Updated 6 years ago"},"absolute_dates":{"created":"Posted on March 6, 2017","modified":"Updated on June 5, 2020"},"absolute_dates_time":{"created":"Posted on March 6, 2017 12:41 pm","modified":"Updated on June 5, 2020 12:54 pm"},"featured_img_caption":"","series_order":"","_links":{"self":[{"href":"https:\/\/blogs.zeiss.com\/digital-innovation\/en\/wp-json\/wp\/v2\/posts\/562","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/blogs.zeiss.com\/digital-innovation\/en\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/blogs.zeiss.com\/digital-innovation\/en\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/blogs.zeiss.com\/digital-innovation\/en\/wp-json\/wp\/v2\/users\/73"}],"replies":[{"embeddable":true,"href":"https:\/\/blogs.zeiss.com\/digital-innovation\/en\/wp-json\/wp\/v2\/comments?post=562"}],"version-history":[{"count":2,"href":"https:\/\/blogs.zeiss.com\/digital-innovation\/en\/wp-json\/wp\/v2\/posts\/562\/revisions"}],"predecessor-version":[{"id":566,"href":"https:\/\/blogs.zeiss.com\/digital-innovation\/en\/wp-json\/wp\/v2\/posts\/562\/revisions\/566"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/blogs.zeiss.com\/digital-innovation\/en\/wp-json\/wp\/v2\/media\/564"}],"wp:attachment":[{"href":"https:\/\/blogs.zeiss.com\/digital-innovation\/en\/wp-json\/wp\/v2\/media?parent=562"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/blogs.zeiss.com\/digital-innovation\/en\/wp-json\/wp\/v2\/categories?post=562"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/blogs.zeiss.com\/digital-innovation\/en\/wp-json\/wp\/v2\/tags?post=562"},{"taxonomy":"topics","embeddable":true,"href":"https:\/\/blogs.zeiss.com\/digital-innovation\/en\/wp-json\/wp\/v2\/topics?post=562"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}