草庐IT

javascript - 捆绑 API 请求

coder 2024-07-20 原文

我正在创建一个 REST API,并且我一直在研究允许捆绑来自客户端的请求的想法。我所说的捆绑是指他们可以发送一个包含多个“真实”请求的请求,然后将它们一起交付给客户。通常是 javascript ajax 请求。像这样:

POST /bundlerequest

["/person/3243", "/person/3243/friends", "/comments/3243?pagesize=10&page=1", "/products", "/product/categories" ] 

(绑定(bind)的请求只能是GET请求,至少目前是这样) 这是为了返回这样的东西

{
    "success" : ["/person/3243", "/person/3243/friends", "/comments/3243?pagesize=10&page=1", "/products", "/product/categories" ],
    "error" : [],
    "completiontime" : 94,
    other relevant metadata...
    "responses" : [
        {"key" : "/person/3243" , "data" : {"name" : "John", ...} },
        {"key" : "/person/3243/friends" , "data" : [{"name": "Peter", "commonfriends" : 5, ...}] },
        etc...
    ]
}

这种捆绑的好处是它减少了请求的数量,这在例如移动设备上尤为重要。

所以我的第一个问题是,我的方法好吗?有没有人有过做这样的事情的经验?

据我所知,解决此问题的常用方法是编写服务器端代码以返回组合数据,我认为这与客户端相关。 (例如,Twitter 用户流就是这样做的,它结合了个人信息、最新推文、最新个人消息等)但这使得 API 非常固执己见,当客户端需要更改时,服务器可能需要更改以适应优化。

第二个问题是如何实现这个?

我的后端是 ASP.NET MVC 3 和 IIS 7。我是否应该在应用程序中实现它,让 bundlerequest 操作在内部调用请求中指定的其他操作?

可以直接在IIS 7中实现吗?编写一个模块透明地拦截对/bundlerequest 的请求,然后调用所有相应的子请求,使应用程序完全不知道发生的捆绑?这也将允许我以与应用程序无关的方式实现它。

最佳答案

你可以使用 asynchronous controller在服务器上聚合这些请求。让我们首先定义一个将由 Controller 返回的 View 模型:

public class BundleRequest
{
    public string[] Urls { get; set; }
}

public class BundleResponse
{
    public IList<string> Success { get; set; }
    public IList<string> Error { get; set; }
    public IList<Response> Responses { get; set; }
}

public class Response
{
    public string Key { get; set; }
    public object Data { get; set; }
}

然后是 Controller :

public class BundleController : AsyncController
{
    public void IndexAsync(BundleRequest request)
    {
        AsyncManager.OutstandingOperations.Increment();
        var tasks = request.Urls.Select(url =>
        {
            var r = WebRequest.Create(url);
            return Task.Factory.FromAsync<WebResponse>(r.BeginGetResponse, r.EndGetResponse, url);
        }).ToArray();

        Task.Factory.ContinueWhenAll(tasks, completedTasks =>
        {
            var bundleResponse = new BundleResponse
            {
                Success = new List<string>(),
                Error = new List<string>(),
                Responses = new List<Response>()
            };
            foreach (var task in completedTasks)
            {
                var url = task.AsyncState as string;
                if (task.Exception == null)
                {
                    using (var response = task.Result)
                    using (var stream = response.GetResponseStream())
                    using (var reader = new StreamReader(stream))
                    {
                        bundleResponse.Success.Add(url);
                        bundleResponse.Responses.Add(new Response
                        {
                            Key = url,
                            Data = new JavaScriptSerializer().DeserializeObject(reader.ReadToEnd())
                        });
                    }
                }
                else
                {
                    bundleResponse.Error.Add(url);
                }
            }
            AsyncManager.Parameters["response"] = bundleResponse;
            AsyncManager.OutstandingOperations.Decrement();
        });
    }

    public ActionResult IndexCompleted(BundleResponse response)
    {
        return Json(response, JsonRequestBehavior.AllowGet);
    }
}

现在我们可以调用它了:

var urls = [ 
    '@Url.Action("index", "person", new { id = 3243 }, Request.Url.Scheme, Request.Url.Host)', 
    '@Url.Action("friends", "person", new { id = 3243 }, Request.Url.Scheme, Request.Url.Host)', 
    '@Url.Action("index", "comments", new { id = 3243, pagesize = 10, page = 1 }, Request.Url.Scheme, Request.Url.Host)',
    '@Url.Action("index", "products", null, Request.Url.Scheme, Request.Url.Host)', 
    '@Url.Action("categories", "product", null, Request.Url.Scheme, Request.Url.Host)' 
];
$.ajax({
    url: '@Url.Action("Index", "Bundle")',
    type: 'POST',
    contentType: 'application/json; charset=utf-8',
    data: JSON.stringify(urls),
    success: function(bundleResponse) {
        // TODO: do something with the response
    }
});

当然,为了适应您的特定需求,可能需要进行一些调整。例如,您提到发送 session 过期的 AJAX 请求,这可能会重定向到登录页面,因此不会捕获错误。这确实是 ASP.NET 中的 PITA。菲尔·哈克 blogged一种以 RESTful 方式规避这种不良行为的可能方法。您只需向请求添加自定义 header 。

关于javascript - 捆绑 API 请求,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/7765500/

有关javascript - 捆绑 API 请求的更多相关文章

  1. ruby-on-rails - Rails HTML 请求渲染 JSON - 2

    在我的Controller中,我通过以下方式在我的index方法中支持HTML和JSON:respond_todo|format|format.htmlformat.json{renderjson:@user}end在浏览器中拉起它时,它会自然地以HTML呈现。但是,当我对/user资源进行内容类型为application/json的curl调用时(因为它是索引方法),我仍然将HTML作为响应。如何获取JSON作为响应?我还需要说明什么? 最佳答案 您应该将.json附加到请求的url,提供的格式在routes.rb的路径中定义。这

  2. ruby-on-rails - ActionController::RoutingError: 未初始化常量 Api::V1::ApiController - 2

    我有用于控制用户任务的Rails5API项目,我有以下错误,但并非总是针对相同的Controller和路由。ActionController::RoutingError:uninitializedconstantApi::V1::ApiController我向您描述了一些我的项目,以更详细地解释错误。应用结构路线scopemodule:'api'donamespace:v1do#=>Loginroutesscopemodule:'login'domatch'login',to:'sessions#login',as:'login',via::postend#=>Teamroutessc

  3. jquery - 我的 jquery AJAX POST 请求无需发送 Authenticity Token (Rails) - 2

    rails中是否有任何规定允许站点的所有AJAXPOST请求在没有authenticity_token的情况下通过?我有一个调用Controller方法的JqueryPOSTajax调用,但我没有在其中放置任何真实性代码,但调用成功。我的ApplicationController确实有'request_forgery_protection'并且我已经改变了config.action_controller.consider_all_requests_local在我的environments/development.rb中为false我还搜索了我的代码以确保我没有重载ajaxSend来发送

  4. 【鸿蒙应用开发系列】- 获取系统设备信息以及版本API兼容调用方式 - 2

    在应用开发中,有时候我们需要获取系统的设备信息,用于数据上报和行为分析。那在鸿蒙系统中,我们应该怎么去获取设备的系统信息呢,比如说获取手机的系统版本号、手机的制造商、手机型号等数据。1、获取方式这里分为两种情况,一种是设备信息的获取,一种是系统信息的获取。1.1、获取设备信息获取设备信息,鸿蒙的SDK包为我们提供了DeviceInfo类,通过该类的一些静态方法,可以获取设备信息,DeviceInfo类的包路径为:ohos.system.DeviceInfo.具体的方法如下:ModifierandTypeMethodDescriptionstatic StringgetAbiList​()Obt

  5. ruby-on-rails - Mandrill API 模板 - 2

    我正在使用Mandrill的RubyAPIGem并使用以下简单的测试模板:testastic按照Heroku指南中的示例,我有以下Ruby代码:require'mandrill'm=Mandrill::API.newrendered=m.templates.render'test-template',[{:header=>'someheadertext',:main_section=>'Themaincontentblock',:footer=>'asdf'}]mail(:to=>"JaysonLane",:subject=>"TestEmail")do|format|format.h

  6. ruby-on-rails - 在 Ruby (on Rails) 中使用 imgur API 获取图像 - 2

    我正在尝试使用Ruby2.0.0和Rails4.0.0提供的API从imgur中提取图像。我已尝试按照Ruby2.0.0文档中列出的各种方式构建http请求,但均无济于事。代码如下:require'net/http'require'net/https'defimgurheaders={"Authorization"=>"Client-ID"+my_client_id}path="/3/gallery/image/#{img_id}.json"uri=URI("https://api.imgur.com"+path)request,data=Net::HTTP::Get.new(path

  7. ruby-on-rails - 使用 HTTParty 的非常基本的 Rails 4.1 API 调用 - 2

    Rails相对较新。我正在尝试调用一个API,它应该向我返回一个唯一的URL。我的应用程序中捆绑了HTTParty。我已经创建了一个UniqueNumberController,并且我已经阅读了几个HTTParty指南,直到我想要什么,但也许我只是有点迷路,真的不知道该怎么做。基本上,我需要做的就是调用API,获取它返回的URL,然后将该URL插入到用户的数据库中。谁能给我指出正确的方向或与我分享一些代码? 最佳答案 假设API为JSON格式并返回如下数据:{"url":"http://example.com/unique-url"

  8. ruby-on-rails - 是否使用 API - 2

    关闭。这个问题是opinion-based.它目前不接受答案。想要改进这个问题?更新问题,以便editingthispost可以用事实和引用来回答它.关闭4年前。Improvethisquestion我的公司有一个巨大的数据库,该数据库接收来自多个来源的(许多)事件,用于监控和报告目的。到目前为止,数据中的每个新仪表板或图形都是一个新的Rails应用程序,在巨大的数据库中有额外的表,并且可以完全访问数据库内容。最近,有一个想法让外部(不是我们公司,而是姊妹公司)客户访问我们的数据,并且决定我们应该公开一个只读的RESTfulAPI来查询我们的数据。我的观点是-我们是否也应该为我们的自己

  9. ruby-on-rails - 使用 javascript 更改数据方法不会更改 ajax 调用用户的什么方法? - 2

    我遇到了一个非常奇怪的问题,我很难解决。在我看来,我有一个与data-remote="true"和data-method="delete"的链接。当我单击该链接时,我可以看到对我的Rails服务器的DELETE请求。返回的JS代码会更改此链接的属性,其中包括href和data-method。再次单击此链接后,我的服务器收到了对新href的请求,但使用的是旧的data-method,即使我已将其从DELETE到POST(它仍然发送一个DELETE请求)。但是,如果我刷新页面,HTML与"new"HTML相同(随返回的JS发生变化),但它实际上发送了正确的请求类型。这就是这个问题令我困惑的

  10. ruby - HTTP 请求中的用户代理,Ruby - 2

    我是Ruby的新手。我试过查看在线文档,但没有找到任何有效的方法。我想在以下HTTP请求botget_response()和get()中包含一个用户代理。有人可以指出我正确的方向吗?#PreliminarycheckthatProggitisupcheck=Net::HTTP.get_response(URI.parse(proggit_url))ifcheck.code!="200"puts"ErrorcontactingProggit"returnend#Attempttogetthejsonresponse=Net::HTTP.get(URI.parse(proggit_url)

随机推荐