1

我收到来自 API 的标准请求。它看起来像这样:

在此处输入图像描述

它的内容类型和长度是:

在此处输入图像描述

但是当这到达我的 Rails 服务器时,Rails 会响应

在此处输入图像描述

我提出这个的原因是因为相同的请求似乎在 SCORM Cloud 的服务器上工作。如果我将完全相同的内容上传给他们,并在调试器中观看,我会看到它发送了一条application/json具有相同请求有效负载的语句,但没有unexpected token错误。

Railsapplication/json请求是否必须以不同于其他服务器的某种方式编写?是否有适当的方法在 Rack Middleware 中重写此行以防止此错误?

更新

的JavaScript:

function _TCDriver_XHR_request (lrs, url, method, data, callback, ignore404, extraHeaders) {
_TCDriver_Log("_TCDriver_XHR_request: " + url);
var xhr,
    finished = false,
    xDomainRequest = false,
    ieXDomain = false,
    ieModeRequest,
    title,
    ticks = ['/', '-', '\\', '|'],
    location = window.location,
    urlParts,
    urlPort,
    result,
    extended,
    until,
    fullUrl = lrs.endpoint + url
;

urlParts = fullUrl.toLowerCase().match(/^(.+):\/\/([^:\/]*):?(\d+)?(\/.*)?$/);

// add extended LMS-specified values to the URL
if (lrs.extended !== undefined) {
    extended = [];
    for (var prop in lrs.extended) {
        if(lrs.extended[prop] != null && lrs.extended[prop].length > 0){
            extended.push(prop + "=" + encodeURIComponent(lrs.extended[prop]));
        }
    }
    if (extended.length > 0) {
        fullUrl += (fullUrl.indexOf("?") > -1 ? "&" : "?") + extended.join("&");
    }
}

//Consolidate headers
var headers = {};
headers["Content-Type"] = "application/json";
headers["Authorization"] = lrs.auth;
if (extraHeaders !== null) {
    for (var headerName in extraHeaders) {
        headers[headerName] = extraHeaders[headerName];
    }
}

//See if this really is a cross domain
xDomainRequest = (location.protocol.toLowerCase() !== urlParts[1] || location.hostname.toLowerCase() !== urlParts[2]);
if (! xDomainRequest) {
    urlPort = (urlParts[3] === null ? ( urlParts[1] === 'http' ? '80' : '443') : urlParts[3]);
    xDomainRequest = (urlPort === location.port);
}

//If it's not cross domain or we're not using IE, use the usual XmlHttpRequest
if (! xDomainRequest || typeof XDomainRequest === 'undefined') {
    _TCDriver_Log("_TCDriver_XHR_request using XMLHttpRequest");
    xhr = new XMLHttpRequest();
    xhr.open(method, fullUrl, callback != null);
    for (var headerName in headers) {
        xhr.setRequestHeader(headerName, headers[headerName]);
    }
}
//Otherwise, use IE's XDomainRequest object
else {
    _TCDriver_Log("_TCDriver_XHR_request using XDomainRequest");
    ieXDomain = true;
    ieModeRequest = _TCDriver_GetIEModeRequest(method, fullUrl, headers, data);
    xhr = new XDomainRequest ();
    xhr.open(ieModeRequest.method, ieModeRequest.url);
}
4

2 回答 2

2

Rails 在这里“很有帮助”,并假设客户端正确使用“Content-Type”并传递了一个与该内容类型实际匹配的值。换句话说,请求中的有效负载必须是可解析的 JSON,并且传递的值不是有效的 JSON。

当您实现一个并非旨在实现最大互操作性的内部 API 时,这是一件完全合理的事情。Rails 不知道的是,LRS 的文档存储应该是“愚蠢的”,基本上允许客户端将它想要的任何东西推入并得到它想要的任何东西,这就是 SCORM Cloud 接受请求的原因,基本上它只是存储内容类型和内容,然后按要求将它们反刍。

您粘贴的代码来自一个非常旧的库,该库对 Content-Type 标头的实现很差。如果在来自主要电子学习创作工具之一的相对较旧版本的内容之外的任何地方找到此代码,则应更新它以使用最新版本的TinCanJS并改进内容类型处理。

至于在 Rails 上进行这项工作,抱歉我没有太多经验。大概有一个开关或其他东西可以关闭自动请求正文解析,至少这是我使用过的大多数其他框架所具有的。

于 2016-04-08T13:40:13.813 回答
-1

Rails 应用程序/json 请求是否必须以不同于其他服务器的某种方式编写?

不是我不知道。

是否有适当的方法在 Rack Middleware 中重写此行以防止此错误?

可能有一种方法是的,甚至可能没有机架中间件,尽管在没有实际请求的情况下很难帮助您。

于 2016-04-08T11:06:15.553 回答