我们正在使用AngularJS和ASP.NET MVC Json Rest API开发单页应用程序。
当未经身份验证的客户端尝试导航到私有路由(例如: / Foo / Home / Template )以获取模板时,它会自动从Web API和我们的AngularJS应用程序获得401响应将其重定向到登录页面。
我们正在使用$http interceptor处理401,其中包含以下内容:
if (response.status === 401) {
$location.path(routeToLogin);
return $q.reject(response);
}
输入正确的凭据允许客户端获取模板。
除了一个细节外,一切都很完美; Javascript控制台报告此错误:
Error: [$compile:tpload] http://errors.angularjs.org/1.3.0/$compile/tpload?p0=%Foo%2FHome%2FTemplate%2F
描述
当$ compile尝试从某些模板获取模板时,会发生此错误 URL,请求失败。
在我们的AngularJs应用程序中,请求失败,但它是设计的,因为资源存在但无法访问(401)。
我应该继续在控制台上接受这种错误,还是可以以某种方式静音或屏蔽它?
修改
我稍微调试了角度源,我发现代码的哪一部分引发了异常
由于我们使用TemplateUrl
来声明模板,因此我们间接使用调用此函数的函数compileTemplateUrl
:
$templateRequest($sce.getTrustedResourceUrl(templateUrl))
这使得ignoreRequestError
的第二个参数(templateRequest
)未定义。
ignoreRequestError(可选)boolean
请求失败时是否忽略异常 模板是空的
当我们的http拦截器处理401状态代码拒绝承诺时,$TemplateRequestProvider
内的$ http.get失败并调用此函数:
function handleError() {
self.totalPendingRequests--;
if (!ignoreRequestError) {
throw $compileMinErr('tpload', 'Failed to load template: {0}', tpl);
}
return $q.reject();
}
我相信我们无法阻止控制台上的错误,因为TemplateUrl
不允许将ignoreRequestError
标记设置为false。
我已尝试绕过401状态码的拒绝;这修复了控制台上的错误,但遗憾的是它有副作用:空模板被错误地缓存到TemplateCache
导致其他问题。
答案 0 :(得分:13)
经过一番思考,我记得在Angular中装饰,它完美地解决了这个问题:
app.config(['$provide', function($provide) {
$provide.decorator('$templateRequest', ['$delegate', function($delegate) {
var fn = $delegate;
$delegate = function(tpl) {
for (var key in fn) {
$delegate[key] = fn[key];
}
return fn.apply(this, [tpl, true]);
};
return $delegate;
}]);
}]);
答案 1 :(得分:0)
您应该能够通过状态和网址拦截模板的调用。
<强> Plunker 强>
app.config(function($httpProvider) {
var interceptor = function($location, $log, $q) {
function success(response) {
// The response if complete
$log.info(response);
return response;
}
function error(response) {
// The request if errors
$log.error(response);
return $q.reject(response);
}
return function(promise) {
return promise.then(success, error);
}
}
$httpProvider.responseInterceptors.push(interceptor);
});
答案 2 :(得分:0)
在我看来,你有两个选择:
跟拦截器一起去。但是,要消除编译,您需要在响应错误(BAD)内返回成功状态代码或重定向到拦截器内的登录页面(好):
app.factory('authInterceptorService', function () {
var interceptor = {};
interceptor.responseError = function (rejection) {
if (rejection.status === 401 && rejection.config.url === "home template url") {
//BAD IDEA
//console.log("faking home template");
//rejection.status = 200;
//rejection.data = "<h1>should log in to the application first</h1>";
//GOOD IDEA
window.location = "/login.html";
}
return rejection;
}
return interceptor;
});
并在app config上:
app.config(['$httpProvider', function ($httpProvider) {
$httpProvider.interceptors.push('authInterceptorService');
}
将主页模板设为公开。毕竟它应该只是html标记,没有任何明智的信息。
这个解决方案很干净......也许也是可能的。