{"id":226,"date":"2021-02-22T01:50:05","date_gmt":"2021-02-22T01:50:05","guid":{"rendered":"https:\/\/vernonkeenan.com\/?p=226"},"modified":"2021-05-30T14:41:14","modified_gmt":"2021-05-30T21:41:14","slug":"i-had-a-go-cors-and-single-page-app-ordeal-so-you-dont-have-to","status":"publish","type":"post","link":"https:\/\/cms.salesforcedevops.net\/index.php\/2021\/02\/22\/i-had-a-go-cors-and-single-page-app-ordeal-so-you-dont-have-to\/","title":{"rendered":"I had a Go, CORS and Single Page App Ordeal So You Don\u2019t Have To"},"content":{"rendered":"\n<p class=\"wp-block-paragraph\">Microservices are awesome, until you need to serve them up in a Single Page Application (SPA). That\u2019s when you need to tame the CORS (cross-origin resource sharing) beast so your fancy new microservices can actually be used by front-end developers.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Don&#8217;t Have a CORS Ordeal<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">I just spent days on this one, so I thought I&#8217;d relay how my final solution works. In my case, I have a swagger-first approach to API development, where I feed a YAML file into <code><a href=\"https:\/\/github.com\/go-swagger\/go-swagger\">go-swagger<\/a><\/code> and then <code>go-swagger<\/code> generates a REST server framework. This works great with lots of microservices that don&#8217;t have any problem communicating using HTTP.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">The problem we encountered was using <a href=\"https:\/\/angular.io\">Angular<\/a> to make a single-page web application that would then use the APIs directly in the browser. That&#8217;s when <a href=\"https:\/\/developer.mozilla.org\/en-US\/docs\/Web\/HTTP\/CORS\">CORS<\/a> comes into play. I couldn&#8217;t get the headers to work right in Go using the <code>go-swagger<\/code> framework.<\/p>\n\n\n\n<figure class=\"wp-block-image size-large\"><img loading=\"lazy\" decoding=\"async\" width=\"1013\" height=\"675\" src=\"https:\/\/ceres-gw.tnxs.net\/wp-content\/uploads\/2021\/02\/pexels-photo-3755755.jpeg\" alt=\"young troubled woman using laptop at home\" class=\"wp-image-258\" srcset=\"https:\/\/cms.salesforcedevops.net\/wp-content\/uploads\/2021\/02\/pexels-photo-3755755.jpeg 1013w, https:\/\/cms.salesforcedevops.net\/wp-content\/uploads\/2021\/02\/pexels-photo-3755755-300x200.jpeg 300w, https:\/\/cms.salesforcedevops.net\/wp-content\/uploads\/2021\/02\/pexels-photo-3755755-1024x682.jpeg 1024w, https:\/\/cms.salesforcedevops.net\/wp-content\/uploads\/2021\/02\/pexels-photo-3755755-768x512.jpeg 768w, https:\/\/cms.salesforcedevops.net\/wp-content\/uploads\/2021\/02\/pexels-photo-3755755-1536x1024.jpeg 1536w\" sizes=\"auto, (max-width: 1013px) 100vw, 1013px\" \/><figcaption>Photo by Andrea Piacquadio on <a href=\"https:\/\/www.pexels.com\/photo\/young-troubled-woman-using-laptop-at-home-3755755\/\" rel=\"nofollow\">Pexels.com<\/a><\/figcaption><\/figure>\n\n\n\n<h2 class=\"wp-block-heading\">Making CORS Work!<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">I have a swagger-first, also known as an <a href=\"https:\/\/swagger.io\/\" rel=\"noreferrer noopener\" target=\"_blank\">OpenAPI standards<\/a>, approach to API development. This is where I feed a YAML file into and then <code>go-swagger<\/code> generates a REST server framework. This works great with lots of microservices that don&#8217;t have any problem communicating using HTTP.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">I could access my microservices externally on a server-to-server basis using <a href=\"https:\/\/apiumbrella.io\/\" target=\"_blank\" rel=\"noreferrer noopener\"><code>api-umbrella<\/code><\/a> as a API gateway. I even think I may have been able to solve my CORS problem with <code>api-umbrella<\/code> configuration, but I didn\u2019t see it.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">I had this problem with Angular, but anyone can have a CORS ordeal when you connect any new REST service to a JavaScript SPA.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">My Toolchain<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">We all get attached to the chain of events that goes from a source code change to finished deployments. I needed my solution to work with a simple API gateway, like <code><a href=\"https:\/\/apiumbrella.io\/\">api-umbrella<\/a><\/code>. Fancy solutions like AWS API Gateway don&#8217;t work for me due to lock-in and cost issues.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">In a nutshell, here are the steps I use to build a microservice:<\/p>\n\n\n\n<ol class=\"wp-block-list\"><li>Hand-write the swagger (OpenAPI v2) file in YAML<\/li><li>Use go-swagger to generate the REST server<\/li><li>Update the code to implement handler functions<\/li><li>Test in VS Code<\/li><li>Use <a href=\"https:\/\/drone.io\/\">Drone CI\/CD<\/a> to generate Docker images in a private registry<\/li><li>Use docker-compose to orchestrate service startup on a private host, in a private VPC, and in a private datacenter<\/li><li>Deploy <code>api-umbrella<\/code> as a the API gateway between public URI&#8217;s and the backend host<\/li><\/ol>\n\n\n\n<h2 class=\"wp-block-heading\">The Journey To Victory<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">After quite a journey, I finally came upon the solution at <a href=\"https:\/\/swagger.io\/docs\/specification\/2-0\/describing-responses\/\">the swagger docs<\/a>. The real trick in taming CORS, though, is to handle the &#8220;pre-flight&#8221; checks a web client makes before the actual REST method is invoked.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">The solution for us is to create an <code>OPTIONS <\/code>method and write the response methods for them in Go using the <code>go-swagger<\/code> framework.<\/p>\n\n\n\n<figure class=\"wp-block-image size-large\"><img decoding=\"async\" src=\"https:\/\/ceres-gw.tnxs.net\/wp-content\/uploads\/2021\/02\/pexels-photo-941693-1.jpeg\" alt=\"man in red crew neck sweatshirt photography\" class=\"wp-image-261\"\/><figcaption>Photo by Andrea Piacquadio on <a href=\"https:\/\/www.pexels.com\/photo\/man-in-red-crew-neck-sweatshirt-photography-941693\/\" rel=\"nofollow\">Pexels.com<\/a><\/figcaption><\/figure>\n\n\n\n<h3 class=\"wp-block-heading\">Make a swagger YAML file<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">This sample OpenAPI (swagger) YAML file is a very simple representation of a single endpoint REST server with two methods.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">To get acquainted with this swagger definition, please note that I&#8217;ve used references rather heavily throughout the file. For example, if you look at the <code>GET \/coordinate<\/code> path definition, you&#8217;ll see a reference to <code>#\/responses\/CoordinateResponse<\/code>. <\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Look in the responses section of the file, and you&#8217;ll see where <code>CoordinateResponse<\/code> includes both a JSON response body and header definitions.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Another handy definition in the responses section of the swagger file is <code>CORSResponse<\/code>, which is used to define the <code>OPTIONS \/coordinate<\/code> response.<\/p>\n\n\n\n<script src=\"https:\/\/gist.github.com\/vkeenan\/691b3bda3c6171a91ba5bf4e3e98a330.js\"><\/script>\n\n\n\n<p class=\"wp-block-paragraph\">In my <code>go-swagger<\/code> environment, this YAML file generates the core HTTP services and frameworks for servicing inbound requests.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Notice how <code>GET \/coordinates<\/code> has an authentication specification and <code>OPTIONS \/coordinates<\/code> has no authentication. I need this because when Angular (or any SPA) causes the web browser to make an outbound call to a CORS-compliant REST server that is not in current origin, the browser expects to receive CORS OPTIONS response without any authentication.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">By the way, you might be able to get around a CORS issue as an API consumer by including a local API proxy that doesn&#8217;t need to use CORS when make a server-to-server HTTP call. But, this technique requires that the API consumer include a proxy in their front-end code.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">I also used a separate \u201ccors\u201d tag which helped organize and separate my \u201cpreflight\u201d CORS options.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Next, I needed to write a preflight CORS handler function in the Go server. That is done by creating Go functions that conform to the go-swagger function conventions, draw from the OpenAPI (swagger) file.<\/p>\n\n\n\n<script src=\"https:\/\/gist.github.com\/vkeenan\/461801396a41f75fbcf87a1a84217a8f.js\"><\/script>\n\n\n\n<h3 class=\"wp-block-heading\">Add CORS Header to Secure&nbsp;Response<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">Almost done. Next I need to modify my <code>GetCoordinate <\/code>handler to add the <code>WithAccessControlAllowHeaders <\/code>modifier.<\/p>\n\n\n\n<script src=\"https:\/\/gist.github.com\/vkeenan\/9a2e1a82fcae6beb77cd52bd4ad8edc4.js\"><\/script>\n\n\n\n<h1 class=\"wp-block-heading\">Thank You!<\/h1>\n\n\n\n<figure class=\"wp-block-image size-large\"><img loading=\"lazy\" decoding=\"async\" width=\"900\" height=\"675\" src=\"https:\/\/ceres-gw.tnxs.net\/wp-content\/uploads\/2021\/02\/pexels-photo-4508643.jpeg\" alt=\"cup of aromatic cappuccino with thank you words on foam\" class=\"wp-image-270\" srcset=\"https:\/\/cms.salesforcedevops.net\/wp-content\/uploads\/2021\/02\/pexels-photo-4508643.jpeg 900w, https:\/\/cms.salesforcedevops.net\/wp-content\/uploads\/2021\/02\/pexels-photo-4508643-300x225.jpeg 300w, https:\/\/cms.salesforcedevops.net\/wp-content\/uploads\/2021\/02\/pexels-photo-4508643-1024x768.jpeg 1024w, https:\/\/cms.salesforcedevops.net\/wp-content\/uploads\/2021\/02\/pexels-photo-4508643-768x576.jpeg 768w, https:\/\/cms.salesforcedevops.net\/wp-content\/uploads\/2021\/02\/pexels-photo-4508643-1536x1152.jpeg 1536w\" sizes=\"auto, (max-width: 900px) 100vw, 900px\" \/><figcaption>Photo by wewe yang on <a href=\"https:\/\/www.pexels.com\/photo\/cup-of-aromatic-cappuccino-with-thank-you-words-on-foam-4508643\/\" rel=\"nofollow\">Pexels.com<\/a><\/figcaption><\/figure>\n\n\n\n<p class=\"wp-block-paragraph\">I hope you liked my \u201clittle\u201d story on how I solved my CORS problem.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">I\u2019m sure I didn\u2019t get it right, so let me know how I could have done it better!<\/p>\n","protected":false},"excerpt":{"rendered":"<p>Microservices are awesome, until you need to serve them up in a Single Page Application (SPA). That\u2019s when you need to tame the CORS (cross-origin resource sharing) beast so your&hellip;<\/p>\n","protected":false},"author":1,"featured_media":250,"comment_status":"open","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"_uag_custom_page_level_css":"","footnotes":""},"categories":[7],"tags":[64],"post_series":[],"class_list":["post-226","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-how-to","tag-tips","entry","has-media"],"yoast_head":"<!-- This site is optimized with the Yoast SEO Premium plugin v22.2 (Yoast SEO v22.2) - https:\/\/yoast.com\/wordpress\/plugins\/seo\/ -->\n<title>I had a Go, CORS and Single Page App Ordeal So You Don\u2019t Have To - SalesforceDevops.net<\/title>\n<meta name=\"description\" content=\"Learn how to use go-swagger to make CORS headers right in the swagger specification and how to implmenet the headers in Go\" \/>\n<meta name=\"robots\" content=\"index, follow, max-snippet:-1, max-image-preview:large, max-video-preview:-1\" \/>\n<link rel=\"canonical\" href=\"https:\/\/cms.salesforcedevops.net\/index.php\/2021\/02\/22\/i-had-a-go-cors-and-single-page-app-ordeal-so-you-dont-have-to\/\" \/>\n<meta property=\"og:locale\" content=\"en_US\" \/>\n<meta property=\"og:type\" content=\"article\" \/>\n<meta property=\"og:title\" content=\"I had a Go, CORS and Single Page App Ordeal So You Don\u2019t Have To - SalesforceDevops.net\" \/>\n<meta property=\"og:description\" content=\"Learn how to use go-swagger to make CORS headers right in the swagger specification and how to implmenet the headers in Go\" \/>\n<meta property=\"og:url\" content=\"https:\/\/cms.salesforcedevops.net\/index.php\/2021\/02\/22\/i-had-a-go-cors-and-single-page-app-ordeal-so-you-dont-have-to\/\" \/>\n<meta property=\"og:site_name\" content=\"SalesforceDevops.net\" \/>\n<meta property=\"article:publisher\" content=\"https:\/\/www.facebook.com\/salesforcedevopsnet\" \/>\n<meta property=\"article:published_time\" content=\"2021-02-22T01:50:05+00:00\" \/>\n<meta property=\"article:modified_time\" content=\"2021-05-30T21:41:14+00:00\" \/>\n<meta property=\"og:image\" content=\"https:\/\/cms.salesforcedevops.net\/wp-content\/uploads\/2021\/02\/idea_sized-00068.jpg\" \/>\n\t<meta property=\"og:image:width\" content=\"1125\" \/>\n\t<meta property=\"og:image:height\" content=\"675\" \/>\n\t<meta property=\"og:image:type\" content=\"image\/jpeg\" \/>\n<meta name=\"author\" content=\"Vernon Keenan\" \/>\n<meta name=\"twitter:card\" content=\"summary_large_image\" \/>\n<meta name=\"twitter:creator\" content=\"@salesforcedevop\" \/>\n<meta name=\"twitter:site\" content=\"@salesforcedevop\" \/>\n<meta name=\"twitter:label1\" content=\"Written by\" \/>\n\t<meta name=\"twitter:data1\" content=\"Vernon Keenan\" \/>\n\t<meta name=\"twitter:label2\" content=\"Est. reading time\" \/>\n\t<meta name=\"twitter:data2\" content=\"5 minutes\" \/>\n<script type=\"application\/ld+json\" class=\"yoast-schema-graph\">{\"@context\":\"https:\/\/schema.org\",\"@graph\":[{\"@type\":\"TechArticle\",\"@id\":\"https:\/\/cms.salesforcedevops.net\/index.php\/2021\/02\/22\/i-had-a-go-cors-and-single-page-app-ordeal-so-you-dont-have-to\/#article\",\"isPartOf\":{\"@id\":\"https:\/\/cms.salesforcedevops.net\/index.php\/2021\/02\/22\/i-had-a-go-cors-and-single-page-app-ordeal-so-you-dont-have-to\/\"},\"author\":{\"name\":\"Vernon Keenan\",\"@id\":\"https:\/\/cms.salesforcedevops.net\/#\/schema\/person\/ac094823465a60be4f47d7321ed7ce04\"},\"headline\":\"I had a Go, CORS and Single Page App Ordeal So You Don\u2019t Have To\",\"datePublished\":\"2021-02-22T01:50:05+00:00\",\"dateModified\":\"2021-05-30T21:41:14+00:00\",\"mainEntityOfPage\":{\"@id\":\"https:\/\/cms.salesforcedevops.net\/index.php\/2021\/02\/22\/i-had-a-go-cors-and-single-page-app-ordeal-so-you-dont-have-to\/\"},\"wordCount\":817,\"commentCount\":0,\"publisher\":{\"@id\":\"https:\/\/cms.salesforcedevops.net\/#organization\"},\"image\":{\"@id\":\"https:\/\/cms.salesforcedevops.net\/index.php\/2021\/02\/22\/i-had-a-go-cors-and-single-page-app-ordeal-so-you-dont-have-to\/#primaryimage\"},\"thumbnailUrl\":\"https:\/\/cms.salesforcedevops.net\/wp-content\/uploads\/2021\/02\/idea_sized-00068.jpg\",\"keywords\":[\"Tips\"],\"articleSection\":[\"How To\"],\"inLanguage\":\"en-US\",\"potentialAction\":[{\"@type\":\"CommentAction\",\"name\":\"Comment\",\"target\":[\"https:\/\/cms.salesforcedevops.net\/index.php\/2021\/02\/22\/i-had-a-go-cors-and-single-page-app-ordeal-so-you-dont-have-to\/#respond\"]}],\"copyrightYear\":\"2021\",\"copyrightHolder\":{\"@id\":\"https:\/\/cms.salesforcedevops.net\/#organization\"}},{\"@type\":\"WebPage\",\"@id\":\"https:\/\/cms.salesforcedevops.net\/index.php\/2021\/02\/22\/i-had-a-go-cors-and-single-page-app-ordeal-so-you-dont-have-to\/\",\"url\":\"https:\/\/cms.salesforcedevops.net\/index.php\/2021\/02\/22\/i-had-a-go-cors-and-single-page-app-ordeal-so-you-dont-have-to\/\",\"name\":\"I had a Go, CORS and Single Page App Ordeal So You Don\u2019t Have To - SalesforceDevops.net\",\"isPartOf\":{\"@id\":\"https:\/\/cms.salesforcedevops.net\/#website\"},\"primaryImageOfPage\":{\"@id\":\"https:\/\/cms.salesforcedevops.net\/index.php\/2021\/02\/22\/i-had-a-go-cors-and-single-page-app-ordeal-so-you-dont-have-to\/#primaryimage\"},\"image\":{\"@id\":\"https:\/\/cms.salesforcedevops.net\/index.php\/2021\/02\/22\/i-had-a-go-cors-and-single-page-app-ordeal-so-you-dont-have-to\/#primaryimage\"},\"thumbnailUrl\":\"https:\/\/cms.salesforcedevops.net\/wp-content\/uploads\/2021\/02\/idea_sized-00068.jpg\",\"datePublished\":\"2021-02-22T01:50:05+00:00\",\"dateModified\":\"2021-05-30T21:41:14+00:00\",\"description\":\"Learn how to use go-swagger to make CORS headers right in the swagger specification and how to implmenet the headers in Go\",\"inLanguage\":\"en-US\",\"potentialAction\":[{\"@type\":\"ReadAction\",\"target\":[\"https:\/\/cms.salesforcedevops.net\/index.php\/2021\/02\/22\/i-had-a-go-cors-and-single-page-app-ordeal-so-you-dont-have-to\/\"]}]},{\"@type\":\"ImageObject\",\"inLanguage\":\"en-US\",\"@id\":\"https:\/\/cms.salesforcedevops.net\/index.php\/2021\/02\/22\/i-had-a-go-cors-and-single-page-app-ordeal-so-you-dont-have-to\/#primaryimage\",\"url\":\"https:\/\/cms.salesforcedevops.net\/wp-content\/uploads\/2021\/02\/idea_sized-00068.jpg\",\"contentUrl\":\"https:\/\/cms.salesforcedevops.net\/wp-content\/uploads\/2021\/02\/idea_sized-00068.jpg\",\"width\":1125,\"height\":675,\"caption\":\"Ordeal of boiling water from a Sachsenspiegel manuscript (1350-1375). Photo courtesy the Herzog August Bibliothek, Wolfenb\u00fcttel, Germany\"},{\"@type\":\"WebSite\",\"@id\":\"https:\/\/cms.salesforcedevops.net\/#website\",\"url\":\"https:\/\/cms.salesforcedevops.net\/\",\"name\":\"SalesforceDevops.net\",\"description\":\"Elevating Salesforce Devops with Insights and Innovation\",\"publisher\":{\"@id\":\"https:\/\/cms.salesforcedevops.net\/#organization\"},\"potentialAction\":[{\"@type\":\"SearchAction\",\"target\":{\"@type\":\"EntryPoint\",\"urlTemplate\":\"https:\/\/cms.salesforcedevops.net\/?s={search_term_string}\"},\"query-input\":\"required name=search_term_string\"}],\"inLanguage\":\"en-US\"},{\"@type\":\"Organization\",\"@id\":\"https:\/\/cms.salesforcedevops.net\/#organization\",\"name\":\"SalesforceDevops.net\",\"url\":\"https:\/\/cms.salesforcedevops.net\/\",\"logo\":{\"@type\":\"ImageObject\",\"inLanguage\":\"en-US\",\"@id\":\"https:\/\/cms.salesforcedevops.net\/#\/schema\/logo\/image\/\",\"url\":\"https:\/\/origin.salesforcedevops.net\/wp-content\/uploads\/2021\/04\/logo-horiz-325.jpg\",\"contentUrl\":\"https:\/\/origin.salesforcedevops.net\/wp-content\/uploads\/2021\/04\/logo-horiz-325.jpg\",\"width\":325,\"height\":101,\"caption\":\"SalesforceDevops.net\"},\"image\":{\"@id\":\"https:\/\/cms.salesforcedevops.net\/#\/schema\/logo\/image\/\"},\"sameAs\":[\"https:\/\/www.facebook.com\/salesforcedevopsnet\",\"https:\/\/twitter.com\/salesforcedevop\",\"https:\/\/www.linkedin.com\/in\/vernonkeenan\",\"https:\/\/www.youtube.com\/channel\/UCOgOn9rD5gyXSOmV7-Q0n7g\"]},{\"@type\":\"Person\",\"@id\":\"https:\/\/cms.salesforcedevops.net\/#\/schema\/person\/ac094823465a60be4f47d7321ed7ce04\",\"name\":\"Vernon Keenan\",\"image\":{\"@type\":\"ImageObject\",\"inLanguage\":\"en-US\",\"@id\":\"https:\/\/cms.salesforcedevops.net\/#\/schema\/person\/image\/\",\"url\":\"https:\/\/cms.salesforcedevops.net\/wp-content\/wphb-cache\/gravatar\/09b\/09bd30f3ca2e049fbd8b9313ef5a41aex96.jpg\",\"contentUrl\":\"https:\/\/cms.salesforcedevops.net\/wp-content\/wphb-cache\/gravatar\/09b\/09bd30f3ca2e049fbd8b9313ef5a41aex96.jpg\",\"caption\":\"Vernon Keenan\"},\"description\":\"Vernon Keenan (LinkedIn) works as a senior information technology industry consultant based in Oakland, California. He earned his B.Sc. in Biomedical Engineering at Northwestern University where he programmed a PDP-8 with punched paper tape. In his 34-year-long career he has been a teacher, SPSS programmer, database administrator, clinical researcher, technology journalist, product marketing manager, market researcher, management consultant, and industry analyst. Most recently he is a telecom operator, cloud architect, Go devops engineer and Salesforce Developer\/Architect. For inquiries about Salesforce strategy briefings or solution architect work please contact Vern directly at +1-510-679-1900 or vern@vernonkeenan.com.\",\"sameAs\":[\"https:\/\/ceres-gw.tnxs.net\",\"https:\/\/linkedin.com\/in\/vernonkeenan\",\"https:\/\/twitter.com\/salesforcedevop\"],\"url\":\"https:\/\/cms.salesforcedevops.net\/index.php\/author\/vern\/\"}]}<\/script>\n<!-- \/ Yoast SEO Premium plugin. -->","yoast_head_json":{"title":"I had a Go, CORS and Single Page App Ordeal So You Don\u2019t Have To - SalesforceDevops.net","description":"Learn how to use go-swagger to make CORS headers right in the swagger specification and how to implmenet the headers in Go","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:\/\/cms.salesforcedevops.net\/index.php\/2021\/02\/22\/i-had-a-go-cors-and-single-page-app-ordeal-so-you-dont-have-to\/","og_locale":"en_US","og_type":"article","og_title":"I had a Go, CORS and Single Page App Ordeal So You Don\u2019t Have To - SalesforceDevops.net","og_description":"Learn how to use go-swagger to make CORS headers right in the swagger specification and how to implmenet the headers in Go","og_url":"https:\/\/cms.salesforcedevops.net\/index.php\/2021\/02\/22\/i-had-a-go-cors-and-single-page-app-ordeal-so-you-dont-have-to\/","og_site_name":"SalesforceDevops.net","article_publisher":"https:\/\/www.facebook.com\/salesforcedevopsnet","article_published_time":"2021-02-22T01:50:05+00:00","article_modified_time":"2021-05-30T21:41:14+00:00","og_image":[{"width":1125,"height":675,"url":"https:\/\/cms.salesforcedevops.net\/wp-content\/uploads\/2021\/02\/idea_sized-00068.jpg","type":"image\/jpeg"}],"author":"Vernon Keenan","twitter_card":"summary_large_image","twitter_creator":"@salesforcedevop","twitter_site":"@salesforcedevop","twitter_misc":{"Written by":"Vernon Keenan","Est. reading time":"5 minutes"},"schema":{"@context":"https:\/\/schema.org","@graph":[{"@type":"TechArticle","@id":"https:\/\/cms.salesforcedevops.net\/index.php\/2021\/02\/22\/i-had-a-go-cors-and-single-page-app-ordeal-so-you-dont-have-to\/#article","isPartOf":{"@id":"https:\/\/cms.salesforcedevops.net\/index.php\/2021\/02\/22\/i-had-a-go-cors-and-single-page-app-ordeal-so-you-dont-have-to\/"},"author":{"name":"Vernon Keenan","@id":"https:\/\/cms.salesforcedevops.net\/#\/schema\/person\/ac094823465a60be4f47d7321ed7ce04"},"headline":"I had a Go, CORS and Single Page App Ordeal So You Don\u2019t Have To","datePublished":"2021-02-22T01:50:05+00:00","dateModified":"2021-05-30T21:41:14+00:00","mainEntityOfPage":{"@id":"https:\/\/cms.salesforcedevops.net\/index.php\/2021\/02\/22\/i-had-a-go-cors-and-single-page-app-ordeal-so-you-dont-have-to\/"},"wordCount":817,"commentCount":0,"publisher":{"@id":"https:\/\/cms.salesforcedevops.net\/#organization"},"image":{"@id":"https:\/\/cms.salesforcedevops.net\/index.php\/2021\/02\/22\/i-had-a-go-cors-and-single-page-app-ordeal-so-you-dont-have-to\/#primaryimage"},"thumbnailUrl":"https:\/\/cms.salesforcedevops.net\/wp-content\/uploads\/2021\/02\/idea_sized-00068.jpg","keywords":["Tips"],"articleSection":["How To"],"inLanguage":"en-US","potentialAction":[{"@type":"CommentAction","name":"Comment","target":["https:\/\/cms.salesforcedevops.net\/index.php\/2021\/02\/22\/i-had-a-go-cors-and-single-page-app-ordeal-so-you-dont-have-to\/#respond"]}],"copyrightYear":"2021","copyrightHolder":{"@id":"https:\/\/cms.salesforcedevops.net\/#organization"}},{"@type":"WebPage","@id":"https:\/\/cms.salesforcedevops.net\/index.php\/2021\/02\/22\/i-had-a-go-cors-and-single-page-app-ordeal-so-you-dont-have-to\/","url":"https:\/\/cms.salesforcedevops.net\/index.php\/2021\/02\/22\/i-had-a-go-cors-and-single-page-app-ordeal-so-you-dont-have-to\/","name":"I had a Go, CORS and Single Page App Ordeal So You Don\u2019t Have To - SalesforceDevops.net","isPartOf":{"@id":"https:\/\/cms.salesforcedevops.net\/#website"},"primaryImageOfPage":{"@id":"https:\/\/cms.salesforcedevops.net\/index.php\/2021\/02\/22\/i-had-a-go-cors-and-single-page-app-ordeal-so-you-dont-have-to\/#primaryimage"},"image":{"@id":"https:\/\/cms.salesforcedevops.net\/index.php\/2021\/02\/22\/i-had-a-go-cors-and-single-page-app-ordeal-so-you-dont-have-to\/#primaryimage"},"thumbnailUrl":"https:\/\/cms.salesforcedevops.net\/wp-content\/uploads\/2021\/02\/idea_sized-00068.jpg","datePublished":"2021-02-22T01:50:05+00:00","dateModified":"2021-05-30T21:41:14+00:00","description":"Learn how to use go-swagger to make CORS headers right in the swagger specification and how to implmenet the headers in Go","inLanguage":"en-US","potentialAction":[{"@type":"ReadAction","target":["https:\/\/cms.salesforcedevops.net\/index.php\/2021\/02\/22\/i-had-a-go-cors-and-single-page-app-ordeal-so-you-dont-have-to\/"]}]},{"@type":"ImageObject","inLanguage":"en-US","@id":"https:\/\/cms.salesforcedevops.net\/index.php\/2021\/02\/22\/i-had-a-go-cors-and-single-page-app-ordeal-so-you-dont-have-to\/#primaryimage","url":"https:\/\/cms.salesforcedevops.net\/wp-content\/uploads\/2021\/02\/idea_sized-00068.jpg","contentUrl":"https:\/\/cms.salesforcedevops.net\/wp-content\/uploads\/2021\/02\/idea_sized-00068.jpg","width":1125,"height":675,"caption":"Ordeal of boiling water from a Sachsenspiegel manuscript (1350-1375). Photo courtesy the Herzog August Bibliothek, Wolfenb\u00fcttel, Germany"},{"@type":"WebSite","@id":"https:\/\/cms.salesforcedevops.net\/#website","url":"https:\/\/cms.salesforcedevops.net\/","name":"SalesforceDevops.net","description":"Elevating Salesforce Devops with Insights and Innovation","publisher":{"@id":"https:\/\/cms.salesforcedevops.net\/#organization"},"potentialAction":[{"@type":"SearchAction","target":{"@type":"EntryPoint","urlTemplate":"https:\/\/cms.salesforcedevops.net\/?s={search_term_string}"},"query-input":"required name=search_term_string"}],"inLanguage":"en-US"},{"@type":"Organization","@id":"https:\/\/cms.salesforcedevops.net\/#organization","name":"SalesforceDevops.net","url":"https:\/\/cms.salesforcedevops.net\/","logo":{"@type":"ImageObject","inLanguage":"en-US","@id":"https:\/\/cms.salesforcedevops.net\/#\/schema\/logo\/image\/","url":"https:\/\/origin.salesforcedevops.net\/wp-content\/uploads\/2021\/04\/logo-horiz-325.jpg","contentUrl":"https:\/\/origin.salesforcedevops.net\/wp-content\/uploads\/2021\/04\/logo-horiz-325.jpg","width":325,"height":101,"caption":"SalesforceDevops.net"},"image":{"@id":"https:\/\/cms.salesforcedevops.net\/#\/schema\/logo\/image\/"},"sameAs":["https:\/\/www.facebook.com\/salesforcedevopsnet","https:\/\/twitter.com\/salesforcedevop","https:\/\/www.linkedin.com\/in\/vernonkeenan","https:\/\/www.youtube.com\/channel\/UCOgOn9rD5gyXSOmV7-Q0n7g"]},{"@type":"Person","@id":"https:\/\/cms.salesforcedevops.net\/#\/schema\/person\/ac094823465a60be4f47d7321ed7ce04","name":"Vernon Keenan","image":{"@type":"ImageObject","inLanguage":"en-US","@id":"https:\/\/cms.salesforcedevops.net\/#\/schema\/person\/image\/","url":"https:\/\/cms.salesforcedevops.net\/wp-content\/wphb-cache\/gravatar\/09b\/09bd30f3ca2e049fbd8b9313ef5a41aex96.jpg","contentUrl":"https:\/\/cms.salesforcedevops.net\/wp-content\/wphb-cache\/gravatar\/09b\/09bd30f3ca2e049fbd8b9313ef5a41aex96.jpg","caption":"Vernon Keenan"},"description":"Vernon Keenan (LinkedIn) works as a senior information technology industry consultant based in Oakland, California. He earned his B.Sc. in Biomedical Engineering at Northwestern University where he programmed a PDP-8 with punched paper tape. In his 34-year-long career he has been a teacher, SPSS programmer, database administrator, clinical researcher, technology journalist, product marketing manager, market researcher, management consultant, and industry analyst. Most recently he is a telecom operator, cloud architect, Go devops engineer and Salesforce Developer\/Architect. For inquiries about Salesforce strategy briefings or solution architect work please contact Vern directly at +1-510-679-1900 or vern@vernonkeenan.com.","sameAs":["https:\/\/ceres-gw.tnxs.net","https:\/\/linkedin.com\/in\/vernonkeenan","https:\/\/twitter.com\/salesforcedevop"],"url":"https:\/\/cms.salesforcedevops.net\/index.php\/author\/vern\/"}]}},"uagb_featured_image_src":{"full":["https:\/\/cms.salesforcedevops.net\/wp-content\/uploads\/2021\/02\/idea_sized-00068.jpg",1125,675,false],"thumbnail":["https:\/\/cms.salesforcedevops.net\/wp-content\/uploads\/2021\/02\/idea_sized-00068-150x150.jpg",150,150,true],"medium":["https:\/\/cms.salesforcedevops.net\/wp-content\/uploads\/2021\/02\/idea_sized-00068-300x180.jpg",300,180,true],"medium_large":["https:\/\/cms.salesforcedevops.net\/wp-content\/uploads\/2021\/02\/idea_sized-00068-768x461.jpg",768,461,true],"large":["https:\/\/cms.salesforcedevops.net\/wp-content\/uploads\/2021\/02\/idea_sized-00068-1024x614.jpg",980,588,true],"1536x1536":["https:\/\/cms.salesforcedevops.net\/wp-content\/uploads\/2021\/02\/idea_sized-00068.jpg",1125,675,false],"2048x2048":["https:\/\/cms.salesforcedevops.net\/wp-content\/uploads\/2021\/02\/idea_sized-00068.jpg",1125,675,false],"lightbox":["https:\/\/cms.salesforcedevops.net\/wp-content\/uploads\/2021\/02\/idea_sized-00068.jpg",1125,675,false],"search_results":["https:\/\/cms.salesforcedevops.net\/wp-content\/uploads\/2021\/02\/idea_sized-00068-125x125.jpg",125,125,true],"blog_entry":["https:\/\/cms.salesforcedevops.net\/wp-content\/uploads\/2021\/02\/idea_sized-00068-750x450.jpg",750,450,true],"blog_post":["https:\/\/cms.salesforcedevops.net\/wp-content\/uploads\/2021\/02\/idea_sized-00068.jpg",750,450,false],"blog_post_full":["https:\/\/cms.salesforcedevops.net\/wp-content\/uploads\/2021\/02\/idea_sized-00068.jpg",1125,675,false],"blog_related":["https:\/\/cms.salesforcedevops.net\/wp-content\/uploads\/2021\/02\/idea_sized-00068.jpg",1125,675,false],"gallery":["https:\/\/cms.salesforcedevops.net\/wp-content\/uploads\/2021\/02\/idea_sized-00068.jpg",1125,675,false]},"uagb_author_info":{"display_name":"Vernon Keenan","author_link":"https:\/\/cms.salesforcedevops.net\/index.php\/author\/vern\/"},"uagb_comment_info":0,"uagb_excerpt":"Microservices are awesome, until you need to serve them up in a Single Page Application (SPA). That\u2019s when you need to tame the CORS (cross-origin resource sharing) beast so your&hellip;","_links":{"self":[{"href":"https:\/\/cms.salesforcedevops.net\/index.php\/wp-json\/wp\/v2\/posts\/226","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/cms.salesforcedevops.net\/index.php\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/cms.salesforcedevops.net\/index.php\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/cms.salesforcedevops.net\/index.php\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/cms.salesforcedevops.net\/index.php\/wp-json\/wp\/v2\/comments?post=226"}],"version-history":[{"count":1,"href":"https:\/\/cms.salesforcedevops.net\/index.php\/wp-json\/wp\/v2\/posts\/226\/revisions"}],"predecessor-version":[{"id":2749,"href":"https:\/\/cms.salesforcedevops.net\/index.php\/wp-json\/wp\/v2\/posts\/226\/revisions\/2749"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/cms.salesforcedevops.net\/index.php\/wp-json\/wp\/v2\/media\/250"}],"wp:attachment":[{"href":"https:\/\/cms.salesforcedevops.net\/index.php\/wp-json\/wp\/v2\/media?parent=226"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/cms.salesforcedevops.net\/index.php\/wp-json\/wp\/v2\/categories?post=226"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/cms.salesforcedevops.net\/index.php\/wp-json\/wp\/v2\/tags?post=226"},{"taxonomy":"post_series","embeddable":true,"href":"https:\/\/cms.salesforcedevops.net\/index.php\/wp-json\/wp\/v2\/post_series?post=226"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}