1

下面的代码是我正在运行的。对我来说放轻松的代码风格......我是新人:p

我只是想从一台服务器上的 HTML 页面向另一台服务器上的 API 发出 Ajax GET 请求。我已经爬上了 CORS 山并获胜(这意味着我最初遇到了 CORS 错误,但已经解决了这个问题)。现在我得到了下面的例外。所以这是一个大问题:

使用 Swagger 定义全局 OPTIONS 处理程序以正确响应 Ajax Preflight 请求的正确方法是什么?

或者,如果我是一个完全的菜鸟......请告诉我我做错了什么。我真的很感谢这里的支持......这个让我很难过。

切断“您应该在同一台服务器上运行 HTML 和 Node”。响应... 为了正确扩展和保护您的 API,您应该与前端分开运行您的 API。在我的例子中,前端将是一个完整的 Web 应用程序和用于将视觉创造力与工程才华区分开来的 API。:)

这是场景...

客户端:任何 Web 服务器:使用 jQuery 1.6.2 的 Amazon Linux AMI 上的 Apache 内容:带有表单的简单 html 页面,使用 ajax 对我的 API 进行 GET 或 POST 调用 API 服务器:运行 Node Swagger Express 的 Amazon Linux AMI(更新为当前)行为:浏览到 HTML 页面单击提交按钮异常被打印到控制台

例外:

Error: Path [/ping] defined in Swagger, but OPTIONS operation is not.
    at middleware (/var/node/api/node_modules/swagger-express-mw/node_modules/swagger-node-runner/lib/connect_middleware.js:31:21)
    at Layer.handle [as handle_request] (/var/node/api/node_modules/express/lib/router/layer.js:82:5)
    at trim_prefix (/var/node/api/node_modules/express/lib/router/index.js:302:13)
    at /var/node/api/node_modules/express/lib/router/index.js:270:7
    at Function.proto.process_params (/var/node/api/node_modules/express/lib/router/index.js:321:12)
    at next (/var/node/api/node_modules/express/lib/router/index.js:261:10)
    at /var/node/api/app.js:38:8
    at Layer.handle [as handle_request] (/var/node/api/node_modules/express/lib/router/layer.js:82:5)
    at trim_prefix (/var/node/api/node_modules/express/lib/router/index.js:302:13)
    at /var/node/api/node_modules/express/lib/router/index.js:270:7

结果(由邮递员返回):

{
  "result": "pong"
}

标题(由邮递员返回):

Access-Control-Allow-Credentials → true
Access-Control-Allow-Headers → X-Requested-With,content-type
Access-Control-Allow-Methods → GET, POST, OPTIONS, PUT, PATCH, DELETE
Access-Control-Allow-Origin → *
Connection → keep-alive
Content-Length → 17
Content-Type → application/json; charset=utf-8
Date → Tue, 01 Dec 2015 08:09:03 GMT
ETag → W/"11-df5e0e4c"
X-Powered-By → Express

注意:由于异常,API 没有返回响应。

网页代码:

<!DOCTYPE html>
<html>
<head>
    <meta name="author" content="Rusty Chapin">
    <meta name="description" content="Sample execution of API to create new contact">
    <title>Create New Contact</title>
    <meta name="viewport" content="width=device-width, minimum-scale=1.0, maximum-scale=1.0">
    <script src="http://ajax.aspnetcdn.com/ajax/jQuery/jquery-1.6.2.min.js"></script>
    <script>
        $(document).ready(function(){
           var getResults = function(){
                var contactemail = $('#contactemail').val();
                var contactname = $('#contactname').val();

                $.ajax({
                    type:"POST",
                    url: "http://xxx.xxx.xxx.xxx:10010/contact",
                    dataType: 'json',
                    contentType: 'application/json',
                    data: { contactemail: contactemail, contactname: contactname },
                    success: function(response){
                        $('#results').html('<h2 class="loading">Contact ID: ' + 
                                response[0].contactid + '<br>Contact Email: ' + 
                                response[0].contactemail + '<br>Contact Name: ' + 
                                response[0].contactname + '<h2 />');
                    },
                    error: function(response){
                        $('#results').html('<h2 class="loading">Response: ' + 
                                response + '<h2 />');
                    }
                });
           };


           $('#submit').click(getResults);
        });

   </script>
</head>
<body>
<div class="container">
    <header>
        <h1>Create New Contact</h1>
    </header>
    <form>
        <input type="email" placeholder="Email Address" id="contactemail" />
        <input type="text" placeholder="Name" id="contactname" />
        <button id="submit">Submit</button>
    </form>
    <section id="results">
        <br>
    </section>
    <footer>
       Created for use with...
    </footer>
</div>
</body>
</html>

API 代码:app.js

'use strict';


var SwaggerExpress = require('swagger-express-mw');
var SwaggerUi = require('swagger-tools/middleware/swagger-ui');
var app = require('express')();
module.exports = app; // for testing


var config = {
  appRoot: __dirname // required config
};


SwaggerExpress.create(config, function(err, swaggerExpress) {
    if (err) { throw err; }


    // Add swagger-ui (This must be before swaggerExpress.register)
    app.use(SwaggerUi(swaggerExpress.runner.swagger));

    // Add headers
    app.use(function (req, res, next) {


       // Website you wish to allow to connect
       res.setHeader('Access-Control-Allow-Origin', '*');


       // Request methods you wish to allow
       res.setHeader('Access-Control-Allow-Methods', 'GET, POST, OPTIONS, PUT, PATCH, DELETE');


       // Request headers you wish to allow
       res.setHeader('Access-Control-Allow-Headers', 'X-Requested-With,content-type');


       // Website you wish to allow to connect
       res.setHeader('Content-Type', 'application/json');


       // Pass to next layer of middleware
       next();
    });


    // install middleware
    swaggerExpress.register(app);


    var port = process.env.PORT || 10010;


    app.listen(port);


    if (swaggerExpress.runner.swagger.paths['/ping']) {
      console.log('running at: http://127.0.0.1:' + port);
      console.log('Ping test: http://127.0.0.1:' + port + '/ping');
    }
});

ping.js

'use strict';


var util = require('util');


module.exports = {
  ping: ping
};


function ping(req, res) {
  // this sends back a JSON response which is a single string
  return res.json({ result: 'pong' });
}

招摇的.yaml

swagger: "2.0"
info:
  version: "0.0.1"
  title: My API
# during dev, should point to your local machine
host: xxx.xxx.xxx.xxx:10010
# basePath prefixes all resource paths 
basePath: /
# 
schemes:
  # tip: remove http to make production-grade
  - http
  - https
# format of bodies a client can send (Content-Type)
consumes:
  - application/json
# format of the responses to the client (Accepts)
produces:
  - application/json
paths:
  /contact:
    x-swagger-router-controller: contact
    post:
      description: Creates a new contact
      operationId: create
      parameters:
        - name: contactemail
          in: query
          description: Email address of new contact
          required: true
          type: string
        - name: contactname
          in: query
          description: Name of new contact
          required: false
          type: string
      responses:
        "200":
          description: Success
          schema:
            $ref: "#/definitions/CreateContactSuccess"
        default:
          description: Error
          schema:
            $ref: "#/definitions/ErrorResponse"
  /ping:
    # binds a127 app logic to a route
    x-swagger-router-controller: ping
    get:
      description: Returns 'pong' to the caller
      # used as the method name of the controller
      operationId: ping
      responses:
        "200":
          description: Success
          schema:
            # a pointer to a definition
            $ref: "#/definitions/PingResponse"
        # responses may fall through to errors
        default:
          description: Error
          schema:
            $ref: "#/definitions/ErrorResponse"
  /swagger:
    x-swagger-pipe: swagger_raw
# complex objects have schema definitions
definitions:
  CreateContactSuccess:
    required:
      - contactid
      - contactemail
      - contactname
    properties:
      contactid:
        type: string
      contactemail:
        type: string
      contactname:
        type: string
  PingResponse:
    required:
      - message
    properties:
      message:
        type: string
  ErrorResponse:
    required:
      - message
    properties:
      message:
        type: string

默认.yaml

# swagger configuration file

# values in the swagger hash are system configuration for swagger-node
swagger:

  fittingsDirs: [ api/fittings ]
  defaultPipe: null
  swaggerControllerPipe: swagger_controllers  # defines the standard processing pipe for controllers

  # values defined in the bagpipes key are the bagpipes pipes and fittings definitions
  # (see https://github.com/apigee-127/bagpipes)
  bagpipes:

    _router:
      name: swagger_router
      mockMode: false
      mockControllersDirs: [ api/mocks ]
      controllersDirs: [ api/controllers ]

    _swagger_validate:
      name: swagger_validator
      validateResponse: true

    # pipe for all swagger-node controllers
    swagger_controllers:
      - onError: json_error_handler
      - cors
      - swagger_security
      - _swagger_validate
      - express_compatibility
      - _router

    # pipe to serve swagger (endpoint is in swagger.yaml)
    swagger_raw:
      name: swagger_raw

# any other values in this file are just loaded into the config for application access...
4

0 回答 0