質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.48%
Vue.js

Vue.jsは、Webアプリケーションのインターフェースを構築するためのオープンソースJavaScriptフレームワークです。

Vuetify.js

Vuetify.jsは、マテリアルデザインを基本とするVue.jsのCSSフレームワークです。多くのマテリアルデザインのコンポーネントを提供しており、あらゆるアプリケーションに対応可能。vue-cli用テンプレートがあり、簡単にページを作成できます。

Google Apps Script

Google Apps ScriptはGoogleの製品と第三者のサービスでタスクを自動化するためのJavaScriptのクラウドのスクリプト言語です。

Q&A

解決済

1回答

9236閲覧

Google Apps Script の自作フォームでAccess-Control-Allow-Originのエラー

marogoma

総合スコア11

Vue.js

Vue.jsは、Webアプリケーションのインターフェースを構築するためのオープンソースJavaScriptフレームワークです。

Vuetify.js

Vuetify.jsは、マテリアルデザインを基本とするVue.jsのCSSフレームワークです。多くのマテリアルデザインのコンポーネントを提供しており、あらゆるアプリケーションに対応可能。vue-cli用テンプレートがあり、簡単にページを作成できます。

Google Apps Script

Google Apps ScriptはGoogleの製品と第三者のサービスでタスクを自動化するためのJavaScriptのクラウドのスクリプト言語です。

0グッド

1クリップ

投稿2018/04/30 13:27

GoogleAppsScriptで自作したフォームからスプレッドシートに投稿する際に405エラーが出る問題について質問させて頂きます。

自作のGASフォーム(※公開範囲は自分のみ)にvuetifyを適用し、
後述のindex.html,コード.gs,complete.htmlを記述しました。
フォームであるindex.htmlからdoPost(e)で投稿後にcomplete.htmlに遷移させます。

フォーム入力後のsubmitボタン押下後にコンソールで下記のような405エラーとなります。

Failed to load https://script.google.com/macros/s/(省略)/exec: Response to preflight request doesn't pass access control check: No 'Access-Control-Allow-Origin' header is present on the requested resource. Origin 'https://(省略)by-0lu-script.googleusercontent.com' is therefore not allowed access. The response had HTTP status code 405. Uncaught (in promise) Error: Network Error at e.exports (spread.js:25) at XMLHttpRequest.l.onerror (spread.js:25)

GASのCORSに起因する問題だとは考えられるのですが(参考 https://stackoverflow.com/questions/29525860/google-apps-script-cross-domain-requests-stopped-working/29529913)、
CORS周りの知識が浅く解決できずに居ます。

追記・修正すべき内容のアドバイスをいただけないでしょうか。
よろしくお願い致します。

※参考までにindex.html,コード.gs,complete.htmlの記述内容を下記に添付させていただきます。

index.html <!DOCTYPE html> <html> <head> <link href='https://fonts.googleapis.com/css?family=Roboto:300,400,500,700|Material+Icons' rel="stylesheet"> <link href="https://unpkg.com/vuetify/dist/vuetify.min.css" rel="stylesheet"> </head> <body> <div id="app"> <v-app> <v-form v-model="valid" ref="form" lazy-validation> <v-text-field label="Name" v-model="name" :rules="nameRules" :counter="10" required ></v-text-field> <v-text-field label="E-mail" v-model="email" :rules="emailRules" required ></v-text-field> <v-btn @click="submit" :disabled="!valid" > submit </v-btn> <v-btn @click="clear">clear</v-btn> </v-form> </v-app> </div> <script src="https://unpkg.com/vue/dist/vue.js"></script> <script src="https://unpkg.com/vuetify/dist/vuetify.js"></script> <script src="https://unpkg.com/axios/dist/axios.min.js"></script> <script> new Vue({ el: '#app', data: () => ({ valid: true, name: '', nameRules: [ v => !!v || 'Name is required', v => (v && v.length <= 10) || 'Name must be less than 10 characters' ], email: '', emailRules: [ v => !!v || 'E-mail is required', v => /^\w+([.-]?\w+)*@\w+([.-]?\w+)*(.\w{2,3})+$/.test(v) || 'E-mail must be valid' ], }), methods: { submit () { if (this.$refs.form.validate()) { // Native form submission is not yet supported axios.post('https://script.google.com/macros/s/(ウェブアプリケーションのURL)/exec', { name: this.name, email: this.email, },{ emulateJSON: true }) } }, clear () { this.$refs.form.reset() } } }) </script> </body> </html>

コード.gs

function doGet(e) { return HtmlService.createTemplateFromFile('index').evaluate() .addMetaTag('viewport', 'width=device-width, initial-scale=1, maximum-scale=1, user-scalable=no, minimal-ui'); } function doPost(e) { this.updateSpreadSheet(e); return HtmlService.createHtmlOutputFromFile("complete"); } function updateSpreadSheet(e) { var f = e.parameter; var sheet = SpreadsheetApp.openById("(スプレッドシートのID)"); var table = sheet.getSheetByName("(シートの名前)"); var array = [[f.name, f.email]]; table.getRange(1,1,1,2).setValues(array); }

complete.html

<!DOCTYPE html> <html> <head> <base target="_top"> </head> <body> スプレッドシートへの投稿完了 </body> </html>

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

guest

回答1

0

ベストアンサー

GASではHTTPのOPTIONメソッドのリクエストを許容していないため、axios.postでpreflightリクエストを送る際にこれがOPTIONメソッドで投げられるため、エラーとなっています。

GASのWebアプリケーションでは、GASのクライアント(ここでいうindex.html)とサーバ(ここで言うコード.gs)の通信には google.script.runというライブラリを利用します。

google.script.runに関するドキュメント

今回の場合ですと以下のように修正すれば、直ります。(少し仕様を変えています。 またpost後の処理を省略しています。)

コード.gs

javascript

1function doGet(e) { 2 return HtmlService.createTemplateFromFile('index').evaluate() 3 .addMetaTag('viewport', 'width=device-width, initial-scale=1, maximum-scale=1, user-scalable=no, minimal-ui'); 4} 5 6function updateSpreadSheet(f) { 7 // Some process 8 Logger.log(f); 9 console.log(f); 10 11 // result 12 return {}; 13} 14

index.html

html

1<!DOCTYPE html> 2<html> 3<head> 4 <link href='https://fonts.googleapis.com/css?family=Roboto:300,400,500,700|Material+Icons' rel="stylesheet"> 5 <link href="https://unpkg.com/vuetify/dist/vuetify.min.css" rel="stylesheet"> 6</head> 7<body> 8 <div id="msg"></div> 9 <div id="app"> 10 <v-app> 11 <v-form v-model="valid" ref="form" lazy-validation> 12 <v-text-field 13 label="Name" 14 v-model="name" 15 :rules="nameRules" 16 :counter="10" 17 required 18 ></v-text-field> 19 <v-text-field 20 label="E-mail" 21 v-model="email" 22 :rules="emailRules" 23 required 24 ></v-text-field> 25 26 <v-btn 27 @click="submit" 28 :disabled="!valid" 29 > 30 submit 31 </v-btn> 32 <v-btn @click="clear">clear</v-btn> 33 </v-form> 34 </v-app> 35 </div> 36 37 <script src="https://unpkg.com/vue/dist/vue.js"></script> 38 <script src="https://unpkg.com/vuetify/dist/vuetify.js"></script> 39 40 <script> 41 new Vue({ 42 el: '#app', 43 data: () => ({ 44 valid: true, 45 name: '', 46 nameRules: [ 47 v => !!v || 'Name is required', 48 v => (v && v.length <= 10) || 'Name must be less than 10 characters' 49 ], 50 email: '', 51 emailRules: [ 52 v => !!v || 'E-mail is required', 53 v => /^\w+([.-]?\w+)*@\w+([.-]?\w+)*(.\w{2,3})+$/.test(v) || 'E-mail must be valid' 54 ], 55 }), 56 57 methods: { 58 submit () { 59 if (this.$refs.form.validate()) { 60 google.script.run.withSuccessHandler(function() { 61 document.getElementById('msg').innerHTML = 'スプレッドシートへの投稿完了'; 62 document.getElementById('app').style.display = 'none'; 63 }).updateSpreadSheet({'name': this.name, 'email': this.email}); 64 } 65 }, 66 clear () { 67 this.$refs.form.reset() 68 } 69 } 70}) 71 </script> 72</body> 73</html>

投稿2018/05/08 05:44

soundTricker

総合スコア137

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

marogoma

2018/05/08 13:26

非常に勉強になりました。 ありがとうございます。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.48%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問