donlih2986 2018-02-12 18:14
浏览 281
已采纳

Golang中的OpenAPI规范验证

I want to validate an openapi spec in a similar fashion as its done here : http://bigstickcarpet.com/swagger-parser/www/index.html but the difference is that Ill use GO to code the tool and its only a CLI.

I am trying to use this :

https://github.com/go-openapi/validate

But the main problem is that the documentation is almost non existent. I came here looking for help of someone that might previously used this library and can give me a MINIMAL example of sending a file containing a spec like such and having this library to throw all the errors or warnings in a similar fashion to the online Swagger validator.

I already can read a file and do some manual validation of the fields on it but of course thats not what I need to do and its just a sample.

Additionally, as a secondary question, I want to post this same question on their GitHub repo but I get this :

enter image description here

and I have no idea how to "review" these guidelines so I can post my question.

What I have :

func validate_spec(spec string) []validator_error {
    // RULES HERE. Now I am hardcoding since this is just a dummy app. On the real app we will need to use goapenapi plus a schema validator
    var errors []validator_error
    name_regex, _ := regexp.Compile("^[a-zA-Z]+[ ][a-zA-Z]+")

    // Validate _.name field
        if ( ! gjson.Get(spec, "name").Exists() ) {
            n := validator_error{Path: "_.name", Message: "Does not exist!"}
            errors = append(errors,n)
        }

        if gjson.Get(spec, "name").Exists() {
            if _, ok := gjson.Get(spec, "name").Value().(string); !ok {
                n := validator_error{Path: "_.name", Message: "should be a string"}
                errors = append(errors,n)
            }
            if ( ! name_regex.MatchString(gjson.Get(spec, "name").String() ) ) {
                n := validator_error{Path: "_.name", Message: "should match " + name_regex.String()}
                errors = append(errors,n)
            }
        }
    // ***************************

    // Validate _.age field
        if ( ! gjson.Get(spec, "age").Exists() ) {
            n := validator_error{Path: "_.age", Message: "Does not exist!"}
            errors = append(errors,n)
        }
        if gjson.Get(spec, "age").Exists() {
            if _, ok := gjson.Get(spec, "age").Value().(float64); !ok {
                n := validator_error{Path: "_.age", Message: "should be an int"}
                errors = append(errors,n)
            }

        }
    // ***************************
    return errors
}

What I need :

func validate_spec(spec string) []validator_error {
        // Something like this is what I am looking for. On the above example I am just hard-coding some dummy rules. I need to use the library here to get the validity of the spec being passed.
        return goopenapi.validate(spec )
    }
  • 写回答

1条回答 默认 最新

  • dongzuo9096 2018-02-15 10:29
    关注

    I use https://github.com/go-openapi quite a lot and find that packages very useful to work with OpenAPI spec, validations and other related stuff.

    Validate the spec itself

    Take a look at the following code:

    document, err = loads.Spec(fpath)
    if err != nil {
        return nil, errors.Wrap(err, "Failed to load spec")
    }
    
    document, err = document.Expanded(&spec.ExpandOptions{RelativeBase: fpath})
    if err != nil {
        return nil, errors.Wrap(err, "Failed to expand spec")
    }
    
    if err := validate.Spec(document, strfmt.Default); err != nil {
        return nil, errors.Wrap(err, "Spec is invalid")
    }
    

    First of all, it loads spec. Then it expands all references ($ref-s) in that spec. After that it validates the spec itself.

    Validate by spec

    So the spec itself is correct. Now we want to validate, for example, a request body by that spec.

    // sch here is the schema object that can be extracted from
    // the spec that you created above.
    
    // data is just an interface{} that represents your data
    // structure that you need to validate. data is a struct
    // you decoded a json body into like json.Unmarshal(b, &data)
    
    err := validate.AgainstSchema(sch, data, strfmt.Default)
    ve, ok := err.(*errors.CompositeError)
    
    // now you can extract errors from ve.Errors
    

    I've build some wrappers around it for easy request validations, for example:

    // op here is the OpenAPI operation object that can also be extracted
    // from the spec loaded above.
    if errs := validate.Body(op.Parameters, body); len(errs) > 0 {
        // work with errs
    }
    

    Disclaimer: Some links above lead to the repository oas2 where I am an author and a maintainer. That repository is build on top of go-openapi where I am not the author.

    本回答被题主选为最佳回答 , 对您是否有帮助呢?
    评论

报告相同问题?