如何使用Ionic 2中的POST请求发送数据

时间:2017-06-11 08:34:07

标签: javascript api ionic2 google-fusion-tables http-status-code-401

我使用Google API创建了一个应用,我正在使用Google fusion tables作为后端,所以我也启用了fusion table API。我正在使用ionic 2制作混合应用。 GET非常适合阅读表格而POST给出了一个 error 401

function submitAnswer(button) {
    
    var accessToken = document.getElementById("accessToken").value;
	var query = "https://www.googleapis.com/fusiontables/v2/query?sql=INSERT INTO " + answerTableId + "(Answers,QuestionId,UserID) VALUES ('" + button.value + "','" + currentQueNo + "','" + userId + "')"+key+"&access_token="+accessToken;
	
	var xhttp2 = new XMLHttpRequest();
    xhttp2.onreadystatechange = function() {
    	//alert(this.readyState + " " + this.status);
    	if(this.readyState == 4) {
    		alert(this.responseText);

    	}
    };
    xhttp2.open("POST", query, true);
    xhttp2.setRequestHeader('Authorization',accessToken);
    xhttp2.send();
}

2 个答案:

答案 0 :(得分:0)

也许你只是忘记了#34; Bearer"在您的授权值中:

xhr.setRequestHeader('Authorization', 'Bearer ' + oauthToken.access_token);

或许您在查询中对您的accessToken进行了严格编码(您需要使用encodeURIComponent(accessToken))

如果从浏览器调用此调用而不是从NodeJS调用,则可能会被CORS问题阻止。

此外,与您的问题无关:创建请求的方式对SQL注入非常敏感。一些随机用户可以在不知道任何密码的情况下删除整个数据库。

答案 1 :(得分:0)

Sincw你正在使用离子2,而不是创建像一个延伸主角http的拦截器,就像下面的代码示例应该为你做每一个技巧,我建议你坚持它。因为它是离子2角2 +

首先,创建一个类来扩展 http 类,如api-handler.ts

import { Storage } from '@ionic/storage';
import { environment } from './environment';
import { Injectable } from '@angular/core';
import { Headers, Http, ConnectionBackend, RequestOptions, RequestMethod, RequestOptionsArgs } from '@angular/http';
import 'rxjs/add/operator/map';
import { Observable } from "rxjs/Observable";

import 'rxjs/add/operator/catch';
import 'rxjs/add/operator/do';
import 'rxjs/add/operator/finally';
import 'rxjs/add/observable/throw';
import 'rxjs/add/observable/fromPromise';
import 'rxjs/add/operator/mergeMap';

/*
  Generated class for the ApiHandler provider.

  this is used to make communication with our endpoint where we pass endpoint 
  header information and any form of manipulation
*/
@Injectable()
export class ApiHandler extends Http {
  private bearer: string = 'Plutus';

  constructor(backend: ConnectionBackend, defaultOptions: RequestOptions, private _storage: Storage) {
    super(backend, defaultOptions);
  }

  /**
    * This is used to call our api service by inputing the service url
    * @param service_url 
    * @param method  
    * @param params 
    * @param options 
    * 
    * @return Observable<any>
    */
  callService(service_url: string, method: RequestMethod, params?: any, options?: RequestOptionsArgs): Observable<any> {

    if (params == null) {
      params = {};
    }

    options = this.requestOptions(method, params, options);


    let token_promise: Promise<any> = this._storage.get('token');

    return Observable.fromPromise(token_promise)
      .mergeMap(token => {
        console.log("token from storage", token);
        if (options.headers == null && token != null) {
          options.headers = new Headers({
            'Authorization': `${this.bearer} ${token}`
          });
        }

        return super.request(this.getFullUrl(service_url), options)
          .catch(this.onCatch);
      });
  }


  /**
   * Request options is used to manipulate and handle needed information before
   * it is sent to server
   * @param options
   * @returns {RequestOptionsArgs}
   */
  private requestOptions(method: RequestMethod, params: any, options?: RequestOptionsArgs): RequestOptionsArgs {
    if (options == null) {
      options = new RequestOptions();
    }
    options.method = method;

    if (options.method === RequestMethod.Post || options.method === RequestMethod.Put) {
      options.body = params;
    } else {
      options.params = params;
    }

    return options;
  }

  /**
   * Build API url.
   * and we remove any leading / from the service calls since 
   * we are not needing then in making request calls
   * e.g localhost:1337//base... to localhost:1337/base..
   * @param url
   * @returns {string}
   */
  private getFullUrl(url: string): string {
    if (url.charAt(0) == "/") {
      url = url.substring(1);
    }
    return environment.endpoint + url;
  }


  /**
     * Error handler.
     * @param error
     * @param caught
     * @returns {ErrorObservable}
     */
  private onCatch(error: any, caught: Observable<any>): Observable<any> {
    return Observable.throw(x);
  }

}

如果你观察我在上面代码中添加标题信息的方式,并使用允许任何形式的http方法的请求方法,如Request.Get,Request.Post,Request.Put,Request.Delete等。

其次,在您的 app.module.ts 中,通过将以下内容添加到您的提供商,将该类作为默认的http调用进行任何后端通信:[]

{
      provide: ApiHandler,
      useFactory: (backend: XHRBackend, defaultOptions: RequestOptions, _storage: Storage) => new ApiHandler(backend, defaultOptions, _storage),
      deps: [XHRBackend, RequestOptions, Storage]
    }

然后最后,在你的情况下使用它只需将它添加到你的构造函数,然后像这样直接使用

import { IFeedBack } from './../interfaces/ifeedback';
import { Observable } from 'rxjs/Observable';
import { ApiHandler } from './../util/api-handler';
import { Injectable } from '@angular/core';
import { RequestMethod } from '@angular/http';
import 'rxjs/add/operator/map';

/*
  Generated class for the FeedBackServiceProvider provider.

  See https://angular.io/docs/ts/latest/guide/dependency-injection.html
  for more info on providers and Angular 2 DI.
*/
@Injectable()
export class FeedBackService {

  constructor(private _apiHandler: ApiHandler) {
  }

  /**
   * this is used to create new feedback 
   * @param feedback 
   */
  create(feedback: IFeedBack): Observable<IFeedBack> {
    return this._apiHandler.callService('/feedback', RequestMethod.Post, feedback)
      .map(res => <IFeedBack>res.json());
  }

}

然后你可以使用新的param调用create来发送然后订阅它。

认为这应该会为你提供更好的服务。