【问题标题】:Angular $http.delete + hapijs using swagger + grailsAngular $http.delete + hapijs 使用 swagger + grails
【发布时间】:2015-11-13 15:09:47
【问题描述】:

我有一个有 angular、gulp、hapijs 和 swagger 的客户。这个客户端连接到我在 grails 上运行的 WS。这个 WS 有一个 Swagger.json。

问题是我无法删除作者。不知道怎么回事。

我的角工厂

(function () {
    'use strict';

    angular
        .module('qrbweb')
        .factory('AuthorFactory', ['$http', AuthorFactory]);

    function AuthorFactory($http) {

        var authors = [];

        return {
            list: function () {
                $http.get("http://localhost:3000/authors").then(function (response) {
                    authors = response.data;
                });
            },
            delete: function (id) {
                console.log(id)
                $http.delete("http://localhost:3000/authors/" + id)
                    .success(function (result) {
                        console.log(result);
                    }).error(function () {
                        console.log("error");
                    });
            },
            get: function () {
                return authors;
            }
        };
    }
})();

我的 hapijs 的 index.js

var hapi = require('hapi');
var server = new hapi.Server();
var intert = require('inert');

server.connection({port: 3000});

server.register(intert, function () {
});

server.route({
    method: 'GET',
    path: '/{param*}',
    handler: {
        directory: {
            path: 'src/client/main/',
            redirectToSlash: true,
            index: true
        }
    }
});

server.route({
    method: 'GET',
    path: '/author/{params*}',
    handler: {
        directory: {
            path: 'src/client/main/app/components/author/list/author.list.html'
        }
    }
});

server.route({
    method: 'GET',
    path: '/bower_components/{params*}',
    handler: {
        directory: {
            path: 'bower_components/'
        }
    }
});

server.route({
    method: 'GET',
    path: '/app/{params*}',
    handler: {
        directory: {
            path: 'src/client/main/app/'
        }
    }
});

/**
 * Dynamic routes
 */
var client = require('swagger-client');

server.route({
        method: 'GET',
        path: '/authors/{param*}',
        handler: function (request, reply) {
            var swagger = new client({
                url: 'http://localhost:8080/swagger.json',
                success: function () {
                    swagger.author.list({max: 10, offset: 0}, function (response) {
                        reply(response.data).type('application/json')
                    });
                }
            });
        }
    }
);

server.route({
        method: 'delete',
        path: '/authors/{id}',
        handler: function (request, reply) {
            var swagger = new client({
                url: 'http://localhost:8080/swagger.json',
                success: function () {
                    swagger.author.delete({authorId: request.params.id}, function (response) {
                        reply(response.data).type('application/json')
                    });
                }
            });
        }
    }
);

server.start(function () {
    console.log('Running server at ', server.info.uri);
});

Swagger.json

{
  "swagger": "2.0",
  "info": {
    "version": "1.0.0",
    "title": "Swagger QRBWS",
    "description": "A sample API that uses a petstore as an example to demonstrate features in the swagger-2.0 specification",
    "termsOfService": "http://swagger.io/terms/",
    "contact": {
      "name": "Swagger API Team"
    },
    "license": {
      "name": "MIT"
    }
  },
  "host": "localhost:8080",
  "basePath": "/api",
  "schemes": [
    "http"
  ],
  "consumes": [
    "application/json"
  ],
  "produces": [
    "application/json"
  ],
  "paths": {
    "/author": {
      "get": {
        "tags": [
          "author"
        ],
        "operationId": "list",
        "description": "Returns all pets from the system that the user has access to",
        "produces": [
          "application/json"
        ],
        "parameters": [
          {
            "name": "max",
            "in": "query",
            "description": "The maximum number to list",
            "type": "integer",
            "default": 10,
            "minimum": 1,
            "maximum": 100
          },
          {
            "name": "offset",
            "in": "query",
            "description": "The offset from the first result to list from",
            "type": "integer",
            "default": 0,
            "minimum": 0
          }
        ],
        "responses": {
          "200": {
            "description": "A list of pets.",
            "schema": {
              "type": "array",
              "items": {
                "$ref": "#/definitions/Author"
              }
            }
          }
        }
      },
      "delete": {
        "tags": [
          "author"
        ],
        "summary": "Delete purchase order by ID",
        "description": "For valid response try integer IDs with value < 1000. Anything above 1000 or nonintegers will generate API errors",
        "operationId": "delete",
        "produces": [
          "application/json"
        ],
        "parameters": [
          {
            "in": "query",
            "name": "authorId",
            "description": "Pet id to delete",
            "required": true,
            "type": "test",
            "format": "int64"
          }
        ],
        "responses": {
          "400": {
            "description": "Invalid ID supplied"
          },
          "404": {
            "description": "Order not found"
          }
        }
      }
    }
  },
  "definitions": {
    "Author": {
      "type": "object",
      "required": [
        "id",
        "name",
        "notes"
      ],
      "properties": {
        "id": {
          "type": "integer",
          "format": "int64"
        },
        "name": {
          "type": "string"
        },
        "notes": {
          "type": "string"
        }
      }
    }
  }
}

当我发送删除作者的请求时,会生成:

Request URL:http://localhost:3000/authors/9 
Request Headers Provisional headers are shown
Accept:application/json,text/plain, */*
Origin:http://localhost:3000 
Referer:http://localhost:3000/author 
User-Agent:Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/44.0.2403.155 Safari/537.36

这是错误:

{ url: 'http://localhost:8080/api/author?authorId=8',   method: 'DELETE',   headers:     { server: 'Apache-Coyote/1.1',
     'x-application-context': 'application:development',
     allow: 'HEAD, GET',
     'content-type': 'application/json;charset=UTF-8',
     'transfer-encoding': 'chunked',
     date: 'Thu, 20 Aug 2015 05:31:36 GMT',
     connection: 'close' },   obj:     { [Error: Method Not Allowed]
     original: null,
     response: 
      { domain: [Object],
        _events: {},
        _maxListeners: undefined,
        res: [Object],
        request: [Object],
        req: [Object],
        links: {},
        text: '{"timestamp":1440048697000,"status":405,"error":"Method Not Allowed","exception":"org.springframework.web.HttpRequestMethodNotSupportedException","message":"Request method \'DELETE\' not supported","path":"/api/author"}',
        body: [Object],
        files: {},
        buffered: true,
        headers: [Object],
        header: [Object],
        statusCode: 405,
        status: 405,
        statusType: 4,
        info: false,
        ok: false,
        redirect: false,
        clientError: true,
        serverError: false,
        error: [Object],
        accepted: false,
        noContent: false,
        badRequest: false,
        unauthorized: false,
        notAcceptable: false,
        forbidden: false,
        notFound: false,
        charset: 'UTF-8',
        type: 'application/json',
        setEncoding: [Function],
        redirects: [] },
     status: 405 },   status: 405,   statusText: '{"timestamp":1440048697000,"status":405,"error":"Method Not Allowed","exception":"org.springframework.web.HttpRequestMethodNotSupportedException","message":"Request method \'DELETE\' not supported","path":"/api/author"}',   data: '{"timestamp":1440048697000,"status":405,"error":"Method Not Allowed","exception":"org.springframework.web.HttpRequestMethodNotSupportedException","message":"Request method \'DELETE\' not supported","path":"/api/author"}' }

【问题讨论】:

标签: angularjs grails swagger hapijs


【解决方案1】:

好吧,我正在寻找解决方案并完成为 AngularJS 1.4+ 的 Swagger 规范 2.0 客户端创建自己的集成器

您可以在此处了解更多信息: https://github.com/olaferlandsen/angular-swagger2-client

一些功能:

  • 支持 POST、PUT、GET、DELETE、PATCH 和 CONNECT 请求。
  • 支持查询、路径、formData 和标头中的参数。
  • 支持 API 中具有安全性的 SecuritySchema(仅类型 apiKey)。
  • 默认情况下,PUT 和 POST 请求使用 content-type 发送:application/x-www-form-urlencoded; charset=utf-8。
  • 删除所有尚未在 API 定义中建立的参数。
  • 为参数和支持的数据类型、格式和要求实施预验证器。
  • 基于 LocalStorage 的全局静态和动态默认值。

【讨论】:

    【解决方案2】:

    我的 swagger.json 错了,这是正确的:

    {   "swagger": "2.0",   "info": {
        "version": "1.0.0",
        "title": "Swagger QRBWS",
        "description": "API of QRBWS",
        "termsOfService": "https://github.com/felansu/QRBWS/blob/master/README.md",
        "contact": {
          "name": "Ferran Gonzalez Alonso",
          "url": "https://github.com/felansu/QRBWS/",
          "email": "gaferran@gmail.com"
        },
        "license": {
          "name": "Apache 2.0",
          "url": "http://www.apache.org/licenses/LICENSE-2.0.html"
        }   },   "host": "localhost:8080",   "basePath": "/api",   "schemes": [
        "http",
        "https"   ],   "consumes": [
        "application/json"   ],   "produces": [
        "application/json"   ],   "paths": {
        "/author/": {
          "get": {
            "tags": [
              "author"
            ],
            "operationId": "list",
            "description": "Returns all authors",
            "produces": [
              "application/json"
            ],
            "parameters": [
              {
                "name": "max",
                "in": "query",
                "description": "The maximum number to list",
                "type": "integer",
                "default": 10,
                "minimum": 1,
                "maximum": 100
              },
              {
                "name": "offset",
                "in": "query",
                "description": "The offset from the first result to list from",
                "type": "integer",
                "default": 0,
                "minimum": 0
              }
            ],
            "responses": {
              "200": {
                "description": "A list of authors.",
                "schema": {
                  "type": "array",
                  "items": {
                    "$ref": "#/definitions/Author"
                  }
                }
              }
            }
          },
          "post": {
            "tags": [
              "author"
            ],
            "summary": "Create",
            "description": "Create an author",
            "operationId": "create",
            "produces": [
              "application/json"
            ],
            "parameters": [
              {
                "in": "body",
                "name": "author",
                "description": "Author object",
                "required": true,
                "schema": {
                  "items": {
                    "$ref": "#/definitions/Author"
                  }
                }
              }
            ],
            "responses": {
              "400": {
                "description": "Invalid params supplied"
              },
              "404": {
                "description": "Order not found"
              }
            }
          }
        },
        "/author/{authorId}": {
          "get": {
            "tags": [
              "author"
            ],
            "summary": "Get an author",
            "description": "For valid response an author with authorId param should be exist",
            "operationId": "getById",
            "produces": [
              "application/json"
            ],
            "parameters": [
              {
                "in": "path",
                "name": "authorId",
                "description": "Author id",
                "required": true,
                "type": "integer",
                "format": "int64"
              }
            ],
            "responses": {
              "400": {
                "description": "Invalid ID supplied"
              },
              "404": {
                "description": "Order not found"
              }
            }
          },
          "delete": {
            "tags": [
              "author"
            ],
            "summary": "Delete an author",
            "description": "For valid response an author with authorId param should be exist",
            "operationId": "delete",
            "produces": [
              "application/json"
            ],
            "parameters": [
              {
                "in": "path",
                "name": "authorId",
                "description": "Author id",
                "required": true,
                "type": "integer",
                "format": "int64"
              }
            ],
            "responses": {
              "400": {
                "description": "Invalid ID supplied"
              },
              "404": {
                "description": "Order not found"
              }
            }
          },
          "put": {
            "tags": [
              "author"
            ],
            "summary": "Update",
            "description": "Update an author",
            "operationId": "update",
            "produces": [
              "application/json"
            ],
            "parameters": [
              {
                "in": "body",
                "name": "author",
                "description": "Author object",
                "required": true,
                "schema": {
                  "items": {
                    "$ref": "#/definitions/Author"
                  }
                }
              },
              {
                "in": "path",
                "name": "authorId",
                "description": "Author id",
                "required": true,
                "type": "integer",
                "format": "int64"
              }
            ],
            "responses": {
              "400": {
                "description": "Invalid params supplied"
              },
              "404": {
                "description": "Order not found"
              }
            }
          }
        },
        "/category/": {
          "get": {
            "tags": [
              "category"
            ],
            "operationId": "list",
            "description": "Returns all categories",
            "produces": [
              "application/json"
            ],
            "parameters": [
              {
                "name": "max",
                "in": "query",
                "description": "The maximum number to list",
                "type": "integer",
                "default": 10,
                "minimum": 1,
                "maximum": 100
              },
              {
                "name": "offset",
                "in": "query",
                "description": "The offset from the first result to list from",
                "type": "integer",
                "default": 0,
                "minimum": 0
              }
            ],
            "responses": {
              "200": {
                "description": "A list of categories.",
                "schema": {
                  "type": "array",
                  "items": {
                    "$ref": "#/definitions/Category"
                  }
                }
              }
            }
          },
          "post": {
            "tags": [
              "category"
            ],
            "summary": "Create",
            "description": "Create an category",
            "operationId": "create",
            "produces": [
              "application/json"
            ],
            "parameters": [
              {
                "in": "body",
                "name": "category",
                "description": "Category object",
                "required": true,
                "schema": {
                  "items": {
                    "$ref": "#/definitions/Category"
                  }
                }
              }
            ],
            "responses": {
              "400": {
                "description": "Invalid params supplied"
              },
              "404": {
                "description": "Order not found"
              }
            }
          }
        },
        "/category/{categoryId}": {
          "get": {
            "tags": [
              "category"
            ],
            "summary": "Get an category",
            "description": "For valid response an category with categoryId param should be exist",
            "operationId": "getById",
            "produces": [
              "application/json"
            ],
            "parameters": [
              {
                "in": "path",
                "name": "categoryId",
                "description": "Author id",
                "required": true,
                "type": "integer",
                "format": "int64"
              }
            ],
            "responses": {
              "400": {
                "description": "Invalid ID supplied"
              },
              "404": {
                "description": "Order not found"
              }
            }
          },
          "delete": {
            "tags": [
              "category"
            ],
            "summary": "Delete an category",
            "description": "For valid response an category with categoryId param should be exist",
            "operationId": "delete",
            "produces": [
              "application/json"
            ],
            "parameters": [
              {
                "in": "path",
                "name": "categoryId",
                "description": "Author id",
                "required": true,
                "type": "integer",
                "format": "int64"
              }
            ],
            "responses": {
              "400": {
                "description": "Invalid ID supplied"
              },
              "404": {
                "description": "Order not found"
              }
            }
          },
          "put": {
            "tags": [
              "category"
            ],
            "summary": "Update",
            "description": "Update an category",
            "operationId": "update",
            "produces": [
              "application/json"
            ],
            "parameters": [
              {
                "in": "body",
                "name": "category",
                "description": "Author object",
                "required": true,
                "schema": {
                  "items": {
                    "$ref": "#/definitions/Author"
                  }
                }
              },
              {
                "in": "path",
                "name": "categoryId",
                "description": "Author id",
                "required": true,
                "type": "integer",
                "format": "int64"
              }
            ],
            "responses": {
              "400": {
                "description": "Invalid params supplied"
              },
              "404": {
                "description": "Order not found"
              }
            }
          }
        },
        "/idiom/": {
          "get": {
            "tags": [
              "idiom"
            ],
            "operationId": "list",
            "description": "Returns all categories",
            "produces": [
              "application/json"
            ],
            "parameters": [
              {
                "name": "max",
                "in": "query",
                "description": "The maximum number to list",
                "type": "integer",
                "default": 10,
                "minimum": 1,
                "maximum": 100
              },
              {
                "name": "offset",
                "in": "query",
                "description": "The offset from the first result to list from",
                "type": "integer",
                "default": 0,
                "minimum": 0
              }
            ],
            "responses": {
              "200": {
                "description": "A list of categories.",
                "schema": {
                  "type": "array",
                  "items": {
                    "$ref": "#/definitions/Idiom"
                  }
                }
              }
            }
          },
          "post": {
            "tags": [
              "idiom"
            ],
            "summary": "Create",
            "description": "Create an idiom",
            "operationId": "create",
            "produces": [
              "application/json"
            ],
            "parameters": [
              {
                "in": "body",
                "name": "idiom",
                "description": "Idiom object",
                "required": true,
                "schema": {
                  "items": {
                    "$ref": "#/definitions/Idiom"
                  }
                }
              }
            ],
            "responses": {
              "400": {
                "description": "Invalid params supplied"
              },
              "404": {
                "description": "Order not found"
              }
            }
          }
        },
        "/idiom/{idiomId}": {
          "get": {
            "tags": [
              "idiom"
            ],
            "summary": "Get an idiom",
            "description": "For valid response an idiom with idiomId param should be exist",
            "operationId": "getById",
            "produces": [
              "application/json"
            ],
            "parameters": [
              {
                "in": "path",
                "name": "idiomId",
                "description": "Idiom id",
                "required": true,
                "type": "integer",
                "format": "int64"
              }
            ],
            "responses": {
              "400": {
                "description": "Invalid ID supplied"
              },
              "404": {
                "description": "Order not found"
              }
            }
          },
          "delete": {
            "tags": [
              "idiom"
            ],
            "summary": "Delete an idiom",
            "description": "For valid response an idiom with idiomId param should be exist",
            "operationId": "delete",
            "produces": [
              "application/json"
            ],
            "parameters": [
              {
                "in": "path",
                "name": "idiomId",
                "description": "Author id",
                "required": true,
                "type": "integer",
                "format": "int64"
              }
            ],
            "responses": {
              "400": {
                "description": "Invalid ID supplied"
              },
              "404": {
                "description": "Order not found"
              }
            }
          },
          "put": {
            "tags": [
              "idiom"
            ],
            "summary": "Update",
            "description": "Update an idiom",
            "operationId": "update",
            "produces": [
              "application/json"
            ],
            "parameters": [
              {
                "in": "body",
                "name": "idiom",
                "description": "Author object",
                "required": true,
                "schema": {
                  "items": {
                    "$ref": "#/definitions/Author"
                  }
                }
              },
              {
                "in": "path",
                "name": "idiomId",
                "description": "Author id",
                "required": true,
                "type": "integer",
                "format": "int64"
              }
            ],
            "responses": {
              "400": {
                "description": "Invalid params supplied"
              },
              "404": {
                "description": "Order not found"
              }
            }
          }
        }   },   "definitions": {
        "Author": {
          "type": "object",
          "required": [
            "id",
            "name",
            "notes"
          ],
          "properties": {
            "id": {
              "type": "integer",
              "format": "int64"
            },
            "name": {
              "type": "string"
            },
            "notes": {
              "type": "string"
            }
          }
        },
        "Category": {
          "type": "object",
          "required": [
            "id",
            "description"
          ],
          "properties": {
            "id": {
              "type": "integer",
              "format": "int64"
            },
            "description": {
              "type": "string"
            }
          }
        },
        "Idiom": {
          "type": "object",
          "required": [
            "id",
            "description"
          ],
          "properties": {
            "id": {
              "type": "integer",
              "format": "int64"
            },
            "description": {
              "type": "string"
            }
          }
        }   } }
    

    我的作者工厂:

    (function () {
        'use strict';
    
        angular
            .module('qrbweb')
            .factory('AuthorFactory', ['$http', '$q', AuthorFactory]);
    
        function AuthorFactory($http, $q) {
    
            var url = "http://localhost:3000/authors/";
            var authors = [];
    
            function list() {
                var d = $q.defer();
                $http.get(url).then(function (response, $q) {
                    d.resolve(response);
                    authors = response.data;
                });
                return d.promise;
            }
    
            function remove(id) {
                var d = $q.defer();
                $http.delete(url + id).then(function (response, $q) {
                    d.resolve(response);
                    list();
                });
                return d.promise;
            }
    
            function create(author) {
                var d = $q.defer();
                $http.post(url, author).then(function (response, $q) {
                    d.resolve(response);
                });
                return d.promise;
            }
    
            function update(author) {
                var d = $q.defer();
                $http.put(url + author.id, author).then(function (response, $q) {
                    d.resolve(response);
                });
                return d.promise;
            }
    
            function getById(id) {
                var d = $q.defer();
                $http.get(url + id).then(function (response, $q) {
                    d.resolve(response);
                });
                return d.promise;
            }
    
            function get() {
                return authors;
            }
    
            return {
                list: list,
                remove: remove,
                create: create,
                get: get,
                getById: getById,
                update: update
            };
        }
    })();
    

    最后是我的快乐指数:

    var hapi = require('hapi');
    var server = new hapi.Server();
    var intert = require('inert');
    var routes = require('./routes');
    
    server.connection({port: 3000});
    
    server.register(intert, function () {
    });
    
    server.route(routes);
    
    server.route({
        method: 'GET',
        path: '/{path*}',
        handler: {
            directory: {
                path: 'src/client/main/',
                listing: false,
                index: true
            }
        }
    });
    
    server.route({
        method: 'GET',
        path: '/app/{param*}',
        handler: {
            directory: {
                path: 'src/client/main/app/',
                redirectToSlash: true,
                index: true
            }
        }
    });
    
    server.route({
        method: 'GET',
        path: '/bower_components/{params*}',
        handler: {
            directory: {
                path: 'bower_components/'
            }
        }
    });
    
    server.start(function () {
        console.log('Running server at ', server.info.uri);
    });
    

    非常感谢!

    【讨论】:

      【解决方案3】:

      有些东西不匹配。

      因此端口号、API 路径以及 ID 的指定方式不匹配。我不知道 hapijs 和 swagger 是做什么的,所以我会忽略它们,让你来弥补我的无知 :)

      试试这个

      1. 通过运行curl -i -X DELETE localhost:8080/api/author/8 测试删除端点,如果可行,则说明 Grails 端正在运行。
      2. 修改AngularJS中的端点为$http.delete("http://localhost:8000/api/author/" + id)

      【讨论】:

        猜你喜欢
        • 2016-05-14
        • 2019-02-14
        • 2017-03-08
        • 2015-08-26
        • 2015-08-10
        • 1970-01-01
        • 2021-01-11
        • 2018-08-04
        • 1970-01-01
        相关资源
        最近更新 更多