2014-01-06 62 views
2

我有一個骨幹客戶端應用程序和春天寧靜的服務器。客戶端應用程序位於localhost上,服務器端應用程序位於localhost:8080上。如果我的模型URL設置爲localhost,它將運行POST(明顯失敗)。如果我將URL設置爲正確的localhost:8080,它將運行OPTIONS。Backbone.js執行選項而不是POST

我已經實現了一個OPTIONS控制器,它可以響應請求。我可以在Chrome的開發工具和wfetch中正確地看到API。

但是POST從不運行。

這裏的客戶端代碼:

var cfd = function() { 
    var config = { 
     serverURL: 'http://localhost:8080' 
    }; 

    function init(authString) { 
     var authHash = window.btoa(authString); 

     $.ajaxSetup({ 
      headers: { 
       Authorization: 'Basic ' + authHash 
      } 
     }); 
    } 

    var RegistrationModel = Backbone.Model.extend({ 
     url: config.serverURL, 
     defaults: { 
      regFname: '', 
      regLname: '', 
      regHeardHow: 0 
     } 
    }); 

    var AuthModel = Backbone.Model.extend({ 
     url: config.serverURL, 
     defaults: { 
      action: '' 
     } 
    }); 

    var UserModel = Backbone.Model.extend({ 
     url: config.serverURL + '/user', 
     defaults: { 
      email: '', 
      fName: '', 
      lName: '', 
      heardHow: 0, 
      isDeleted: 0 
     } 
    }); 

    return { 
     AuthModel: AuthModel, 
     RegistrationModel: RegistrationModel, 
     UserModel: UserModel, 
     config: config, 
     init: init 
    }; 
}(); 

而且......

var model; 
cfd.init($('#email').val() + ':'); 

model = new cfd.UserModel({ 
    email: '[email protected]', 
    fName: 'Test', 
    lName: 'Dude', 
    heardHow: 21, 
    isDeleted: 0 
}); 

model.save(); 

這裏是我的API響應選項:

RESPONSE: **************\nHTTP/1.1 200 OK\r\n 
Server: Apache-Coyote/1.1\r\n 
Allow: POST,PUT,GET,DELETE,OPTIONS\r\n 
Content-Length: 0\r\n 
Date: Mon, 06 Jan 2014 16:30:31 GMT\r\n 
\r\n 

我已經響應代碼爲200,並試圖此204.

爲了完整起見,這裏是我的選擇控制器:

@Controller 
public class OptionsController { 

    @Bean 
    public DispatcherServlet dispatcherServlet() { 
     DispatcherServlet servlet = new DispatcherServlet(); 
     servlet.setDispatchOptionsRequest(true); 
     return servlet; 
    } 

    public static ResponseEntity<Void> allows(HttpMethod[] methods) { 
     HttpHeaders headers = new HttpHeaders(); 
     Set<HttpMethod> allow = new HashSet<>(); 
     for(HttpMethod method: methods){ 
      allow.add(method); 
     } 
     headers.setAllow(allow); 
     return new ResponseEntity<>(headers, HttpStatus.OK); 
    } 

    @RequestMapping(method = RequestMethod.OPTIONS) 
    ResponseEntity<Void> getProposalsOptions() { 
     HttpMethod[] methods = new HttpMethod[5]; 
     methods[0] = HttpMethod.GET; 
     methods[1] = HttpMethod.PUT; 
     methods[2] = HttpMethod.POST; 
     methods[3] = HttpMethod.DELETE; 
     methods[4] = HttpMethod.OPTIONS; 

     return allows(methods); 
    } 
} 

和後控制器:

@Controller 
public class PostController { 

    @Inject 
    private UserRepository users; 

    @RequestMapping(value = "/user", method = RequestMethod.POST) 
    public @ResponseBody void insertUser(@RequestBody final User user) { 
     users.save(user); 
    } 
} 

我在做什麼錯?

+0

爲什麼Backbone在這種情況下做PUT?它不應該創造一個新的,發佈? – Lurk21

+0

當isNew()爲true時,Backbone將不會運行PUT調用。這意味着如果在模型上設置了一個id,它將運行一個PUT,否則它會POST。 0,BTW,將返回false,因此將發出POST調用。 – oamsel

+0

哦,當然這是有道理的 – Lurk21

回答

2

正如@ Lurk21所暗示的那樣,您的問題是瀏覽器強制執行的結果same-origin policy。默認情況下,它禁止JavaScript代碼將HTTP請求發送到從其加載的「源」以外的「源」。由於港口是原產地的一部分,http://localhosthttp://localhost:8080被認爲是不同的來源,這會導致問題。

但是,服務器可能通過發送所謂的Crosss-Origin Resource Sharing (CORS)標頭來響應OPTIONS請求來選擇性地允許來自其他來源的請求。這就是爲什麼你在瀏覽器開發工具中看到這樣的請求。由於您的服務器的響應中不包含任何CORS標頭,因此瀏覽器假定不允許來自此URL的跨域請求並中止請求。

要解決此問題,發送標題如與OPTIONS答覆如下:

Access-Control-Allow-Origin: * 
Access-Control-Allow-Methods: GET, PUT, POST, DELETE 

相反的*,你還可以插入你要允許從請求特定的起源。有關您可能需要的其他標題和其他附加詳細信息,請參閱MDN上的CORS文檔(與上面鏈接)。

0

問題是'同源策略'的規則。也許可以用jsonp以某種方式繞過它,但是我需要反向代理,所以我將它添加到我的開發環境中,並且工作。

相關問題