2016-10-04 43 views
23

我有一個項目需要使用Angular2(最終)發佈到舊的,遺留的Tomcat 7服務器,使用.jsp頁面提供一些REST-ish API 。如何強制Angular2使用x-www-form-urlencoded POST POST

當項目只是一個簡單的JQuery應用程序執行AJAX請求時,這工作得很好。但是,該項目的範圍已經擴大,需要使用更現代化的框架來重寫。 Angular2對於這項工作來說看起來很棒,但有一個例外:它拒絕使用任何選項執行POST請求,而是作爲API不提取的表單數據。 API期望所有內容都是urlencoded,依靠Java的request.getParameter("param")語法來提取單個字段。

這是一個從我user.service.ts剪斷:

import { Injectable } from '@angular/core'; 
import { Headers, Response, Http, RequestOptions } from '@angular/http'; 
import { Observable } from 'rxjs/Observable'; 
import 'rxjs/add/operator/map'; 

@Injectable() 
export class UserService { 
    private loggedIn = false; 
    private loginUrl = 'http://localhost:8080/mpadmin/api/login.jsp'; 
    private headers = new Headers({'Content-Type': 'application/x-www-form-urlencoded'}); 

    constructor(private http: Http) {} 

    login(username, password) { 
     return this.http.post(this.loginUrl, {'username': username, 'password': password}, this.headers) 
      .map((response: Response) => { 
       let user = response.json(); 
       if (user) { 
        localStorage.setItem('currentUser', JSON.stringify(user)); 
       } 
      } 
     ); 
    } 
} 

不管我怎麼設置頁眉內容類型是,它總是最終到達非編碼形式的數據。它不尊重我設置的標題。

有沒有其他人遇到過這個?你如何着手強迫Angular2使用request.getParameter("param")可以通過舊的Java API讀取的格式發佈數據?

編輯:對於任何未來發現此問題的人來說,解決方案實際上非常簡單。設置帖子的主體是這樣的:

let body = `username=${username}&password=${password}`;` 

查看Brad的例子。

+1

我認爲角度很蹩腳,很難發佈爲「www-form-urlencoded」。應該有一流的支持來輕鬆​​做到這一點。 – goat

+1

這似乎不再適用於Angular4 +和HttpClient。 – stt106

+0

你是對的,@ stt106。這個解決方案是舊的,並且特定於早於4的早期版本。當我有時間時,我將重寫上面的解決方案以用於HttpClient。 –

回答

39

您可以使用URLSearchParams作爲請求的主體,角度會自動將內容類型設置爲application/x-www-form-urlencoded並正確編碼身體。

let body = new URLSearchParams(); 
body.set('username', username); 
body.set('password', password); 

this.http.post(this.loginUrl, body).map(...); 

它不是目前的工作對你來說你不編碼格式正確的身體數據和你沒有正確設置標題選項的原因。

您需要編碼所述主體是這樣的:

let body = `username=${username}&password=${password}`; 

您需要設置頭選項這樣的:

this.http.post(this.loginUrl, body, { headers: headers }).map(...); 
+3

嘗試了URLSearchParams()選項,該選項無效,但對於正文的格式完全正確。那就是訣竅。標記爲答案,我將更新帖子供其他人查找。 –

+0

我使用'URLSearchParams'作爲表單數據的正文,沒有問題。我認爲它是在RC4中引入的。你使用什麼角度版本? – Brad

+0

最後,但回頭看,我敢肯定我只是打錯了,而且自從第二個選項奏效以後,我沒有再試過。順便再次感謝您的幫助。 –

30

對於角4.3 +/5 +(新了HTTPClient)使用以下:

let body = new URLSearchParams(); 
body.set('user', username); 
body.set('password', password); 

let options = { 
    headers: new HttpHeaders().set('Content-Type', 'application/x-www-form-urlencoded') 
}; 

this.http 
    .post('//yourUrl.com/login', body.toString(), options) 
    .subscribe(response => { 
     //... 
    }); 

注意三件事情,使其按預期工作:

  1. 使用URLSearchParams爲您的身體
  2. 身體轉換成字符串
  3. 設置標頭的內容類型

注意:舊的瀏覽器確實需要一個填充工具!我使用:npm i url-search-params-polyfill --save,然後添加到polyfills。TS:import 'url-search-params-polyfill';

+1

謝謝您將此添加爲答案。 –

+0

拯救我的男人!謝謝! –

+0

夥計們注意你需要一個polyfill!我將它添加到答案中。 – Mick

8

對於那些仍然在尋找一個答案,這是我如何與角5和HttpClient的解決了這個問題:

const formData = new FormData(); 

// append your data 
formData.append('myKey1', 'some value 1'); 
formData.append('myKey1', 'some value 2'); 
formData.append('myKey3', true); 

this.httpClient.post('apiPath', formData); 

設置Content-Type頭,角將解決您的問題!

+0

不錯!感謝您使用Angular 5 HttpClient解決方案。我一直在將我的項目遷移到Angular 5,並正在考慮簡化發佈過程。 –

+0

應該是被接受的答案 – Xan

+0

我需要在頭中包含'Authorization',我是否也將它設置在'formData'上,或者將它設置在'RequestOptions'中? – stt106

0

從Brad身上添加您需要調用body.toString()並將其作爲請求的主體。

+1

這應該是對布拉德答案的評論,而不是一個單獨的答案。 – peacetype