Documentation ¶
Overview ¶
Package ws defines types used by framework and application components involved in web service processing. For more information on how web services work in Granitic, see https://granitic.io/ref/web-services
A brief explanation of the key types and concepts follows.
Requests and responses ¶
Request and Response are abstractions of the HTTP request and response associated with a call to a web service endpoint. By default your application logic will not have access to the underlying HTTP objects (this can be overridden on a per-endpoint basis by setting AllowDirectHTTPAccess to true on your handler - see the package documentation for ws/handler for more information).
Your application code will not directly control how data is parsed into a Request or how the data and/or errors in a Response are rendered to the caller. This is instead handled by the JSONWs or XMLWs facility.
HTTP status codes are determined automatically based on the type (or lack of) errors in the Response object, but this behaviour can be overridden by setting an HTTP status code manually on the Response.
Errors ¶
Errors can be detected or occur during all the phases of request processing (see https://granitic.io/ref/web-services-principles ). If errors are encountered during the parsing and binding phases of request processing, they are referred to as 'framework errors' as they are handled outside of application code. Framework errors result in one of small number of generic error messages being sent to a caller. See https://granitic.io/ref/error-handling for information on how to override these messages or how to allow your application to have visibility of framework errors.
If an error occurs during or after parsing and binding is complete, it will be recorded in the WsReponse.Errors field. These types of errors are called service errors. For more information on service errors, refer to the GoDoc for CategorisedError below or https://granitic.io/ref/service-error-management
Response writing ¶
The serialisation of the data in a Response to an HTTP response is handled by a component implementing ResponseWriter. A component of this type will be automatically created for you when you enable the JSONWs or XMLWs facility.
Parameter binding ¶
Parameter binding refers to the process of automatically capturing request query parameters and injecting them into fields on the Request Body. It also refers to a similar process for extracting information from a request's path using regular expressions. See https://granitic.io/ref/capture-web-service-data for more details.
IAM and versioning ¶
Granitic does not provide implementations of Identity Access Management or request versioning, but instead provides highly generic types to allow your application's implementations of these concepts to be integrated with Grantic's web service request processing. See the GoDoc for Identifier, AccessChecker and handler/WsVersionAssessor and the iam package for more details.
HTTP status code determination ¶
Unless your application defines its own HTTPStatusCodeDeterminer, the eventual HTTP status code set on the response to a web service request it determined by examining the state of a Response using the following logic:
1. If the Response.HTTPStatus field is non-zero, use that.
2. If the Response.Errors.HTTPStatus field is non-zero, use that.
3. If the Response.Errors structure:
a) Contains one or more 'Unexpected' errors, use HTTP 500.
b) Contains an 'HTTP' error, convert that error's code to a number and use that.
c) Contains one or more 'Security' errors, use HTTP 401.
d) Contains one or more 'Client' errors, use HTTP 400.
e) Contains one or more 'Logic' errors, use HTTP 409.
4. Return HTTP 200.
Index ¶
- Constants
- func CategoryToCode(c ServiceErrorCategory) string
- func CategoryToName(c ServiceErrorCategory) string
- func MergeHeaders(res *Response, ch map[string]string, dh map[string]string) map[string]string
- func NewParamsForPath(targets []string, values []string) *types.Params
- func NewParamsForQuery(values url.Values) *types.Params
- func RecoverIDFunction(ctx context.Context) func(context.Context) string
- func RequestID(ctx context.Context) string
- func StoreRequestIDFunction(ctx context.Context, f func(context.Context) string) context.Context
- func WriteHeaders(w http.ResponseWriter, headers map[string]string)
- type AbnormalStatusWriter
- type AccessChecker
- type CategorisedError
- type CommonResponseHeaderBuilder
- type DirectHTTPAccess
- type ErrorFormatter
- type FrameworkError
- type FrameworkErrorEvent
- type FrameworkErrorGenerator
- func (feg *FrameworkErrorGenerator) Error(e FrameworkErrorEvent, c ServiceErrorCategory, a ...interface{}) *CategorisedError
- func (feg *FrameworkErrorGenerator) HTTPError(status int, a ...interface{}) *CategorisedError
- func (feg *FrameworkErrorGenerator) MessageCode(e FrameworkErrorEvent, a ...interface{}) (message string, code string)
- type FrameworkPhase
- type GraniticHTTPStatusCodeDeterminer
- type HTTPStatusCodeDeterminer
- type Identifier
- type MarshalingWriter
- type MarshallingResponseWriter
- type Outcome
- type ParamBinder
- type ProcessState
- type Request
- type Response
- type ResponseWrapper
- type ResponseWriter
- type ServiceErrorCategory
- type ServiceErrorConsumer
- type ServiceErrorFinder
- type ServiceErrors
- type Unmarshaller
Constants ¶
const ( // Unexpected is an unhandled error that will generally result in an HTTP 500 status code being set. Unexpected = iota // Client is a problem that the calling client has caused or could have foreseen, generally resulting in an HTTP 400 status code. Client // Logic is a problem that the calling client could not be expected to have foreseen (email address in use, for example) resulting in an HTTP 409. Logic // Security is an access or authentication error that might result in an HTTP 401 or 403. Security // HTTP is an error that forces a specific HTTP status code. HTTP )
const ( // Unmarshall indicates an error was encountered while trying to parse an HTTP request body into a struct Unmarshall = iota // QueryBind indicates an error was encountered while mapping HTTP query parameters to fields on a struct QueryBind //PathBind indicates an error was encountered while mapping elements of an HTTP request's path to fields on a struct PathBind )
const ( // UnableToParseRequest indicates that the HTTP request could not be parsed UnableToParseRequest = "UnableToParseRequest" // QueryTargetNotArray indicates that a query parameter whose value is a list has been bound to a target field that is not an array QueryTargetNotArray = "QueryTargetNotArray" // QueryWrongType indicates that a query parameter is not compatible with the type of field to which it is bound QueryWrongType = "QueryWrongType" // PathWrongType indicates that a path element is not compatible with the type of field to which it is bound PathWrongType = "PathWrongType" // QueryNoTargetField indicates that no field on the target can be matched to the a named query parameter QueryNoTargetField = "QueryNoTargetField" )
const ( // Normal is a normal outcome resulting in an HTTP 200 response. Normal = iota // Error is an outcome with anticipated and handled errors resulting in a 4xx response. Error // Abnormal is an unexpected or unusual outcome resulting in a 5xx response. Abnormal )
Variables ¶
This section is empty.
Functions ¶
func CategoryToCode ¶
func CategoryToCode(c ServiceErrorCategory) string
CategoryToCode maps a ServiceErrorCategory to the category's name's first letter. For example, Security maps to 'S'
func CategoryToName ¶
func CategoryToName(c ServiceErrorCategory) string
CategoryToName maps a ServiceErrorCategory to the category's name's first letter. For example, Security maps to 'Security'
func MergeHeaders ¶
MergeHeaders merges together the headers that have been defined on the Response, the static default headers attache to this writer and (optionally) those constructed by the ws.CommonResponseHeaderBuilder attached to this writer. The order of precedence, from lowest to highest, is static headers, constructed headers, headers in the Response.
func NewParamsForPath ¶
NewParamsForPath creates a Params used to store the elements of a request path extracted using regular expression groups.
func NewParamsForQuery ¶
NewParamsForQuery creates a Params storing the HTTP query parameters from a request.
func RecoverIDFunction ¶ added in v2.1.0
RecoverIDFunction finds a function in the context that is able to recover a request ID from a context.
func RequestID ¶ added in v2.1.0
RequestID returns the ID stored in the supplied context or "" if there is no ID or if a function for extracting an ID from a context has not been defined and also stored in the context
func StoreRequestIDFunction ¶ added in v2.1.0
StoreRequestIDFunction stores a function in the context that is able to recover a request ID from a context.
func WriteHeaders ¶
func WriteHeaders(w http.ResponseWriter, headers map[string]string)
WriteHeaders writes the supplied map as HTTP headers.
Types ¶
type AbnormalStatusWriter ¶
type AbnormalStatusWriter interface { // Write converts whatever data is present in the supplied state object to the HTTP output stream associated // with the current web service request. WriteAbnormalStatus(ctx context.Context, state *ProcessState) error }
AbnormalStatusWriter is implemented by components able to write a valid response even if the request resulted in an abnormal (5xx) outcome.
type AccessChecker ¶
type AccessChecker interface { // Allowed returns true if the caller is allowed to have this request processed, false otherwise. Allowed(ctx context.Context, r *Request) bool }
AccessChecker is implemented by components that are able to determine if a caller is allowed to have a request processed.
type CategorisedError ¶
type CategorisedError struct { // The broad type of error, which influences the eventual HTTP status code set on the response. Category ServiceErrorCategory // A unique code that a caller can rely on to identify a specific error or that can be used to lookup an error message. Code string // A message suitable for displaying to the caller. Message string //If this error relates to a specific field or parameter in a web service request, this field is set to the name of that field. Field string }
CategorisedError is a service error with a concept of the general 'type' of error it is.
func NewCategorisedError ¶
func NewCategorisedError(category ServiceErrorCategory, code string, message string) *CategorisedError
NewCategorisedError creates a new CategorisedError with every field expect 'Field' set.
type CommonResponseHeaderBuilder ¶
type CommonResponseHeaderBuilder interface {
BuildHeaders(ctx context.Context, state *ProcessState) map[string]string
}
CommonResponseHeaderBuilder is an object that constructs response headers that are common to all web service requests. These may typically be caching instructions or 'processing server' records. Implementations must be extremely cautious when using the information in the supplied WsProcess state as some values may be nil.
type DirectHTTPAccess ¶
type DirectHTTPAccess struct { // The HTTP response output stream. ResponseWriter http.ResponseWriter // The incoming HTTP request. Request *http.Request }
DirectHTTPAccess wraps the underlying low-level HTTP request and response writing objects.
type ErrorFormatter ¶
type ErrorFormatter interface { // FormatErrors converts the supplied errors into a structure that a response writer will use to write the errors to // the current HTTP response. FormatErrors(errors *ServiceErrors) interface{} }
ErrorFormatter is an interface for components able to convert a set of service errors into a structure suitable for serialisation.
type FrameworkError ¶
type FrameworkError struct { // The phase of the request processing during which an error was encountered. Phase FrameworkPhase // The name of the field or parameter in the HTTP request with a problem ClientField string // The name of the field on the response body struct that was being written to TargetField string // A system generated message relating to the error. Message string // The value of the field/parameter that caused the error. Value string // For array parameters, the position in the array that caused the error. Position int // A system generated code for the error. Code string }
FrameworkError an error encountered in early phases of request processing, before application code is invoked.
func NewPathBindFrameworkError ¶
func NewPathBindFrameworkError(message, code, target string) *FrameworkError
NewPathBindFrameworkError creates a FrameworkError with fields set appropriate for an error encountered during mapping elements of the HTTP request's path to fields on a Request's Body.
func NewQueryBindFrameworkError ¶
func NewQueryBindFrameworkError(message, code, param, target string) *FrameworkError
NewQueryBindFrameworkError creates a FrameworkError with fields set appropriate for an error encountered during mapping of HTTP query parameters to fields on a Request's Body
func NewUnmarshallFrameworkError ¶
func NewUnmarshallFrameworkError(message, code string) *FrameworkError
NewUnmarshallFrameworkError creates a FrameworkError with fields set appropriate for an error encountered during parsing of the HTTP request body.
func (*FrameworkError) Error ¶
func (fe *FrameworkError) Error() string
Error returns a string representation of a FrameworkError
func (*FrameworkError) RecordField ¶
func (fe *FrameworkError) RecordField(f string)
RecordField implements FieldAssociatedError
type FrameworkErrorEvent ¶
type FrameworkErrorEvent string
FrameworkErrorEvent uniquely identifies a 'handled' failure during the parsing and binding phases
type FrameworkErrorGenerator ¶
type FrameworkErrorGenerator struct { Messages map[FrameworkErrorEvent][]string HTTPMessages map[string]string FrameworkLogger logging.Logger }
A FrameworkErrorGenerator can create error messages for errors that occur outside of application code and messages that should be displayed when generic HTTP status codes (404, 500, 503 etc) are set.
func (*FrameworkErrorGenerator) Error ¶
func (feg *FrameworkErrorGenerator) Error(e FrameworkErrorEvent, c ServiceErrorCategory, a ...interface{}) *CategorisedError
Error creates a service error given a framework error.
func (*FrameworkErrorGenerator) HTTPError ¶
func (feg *FrameworkErrorGenerator) HTTPError(status int, a ...interface{}) *CategorisedError
HTTPError generates a message to be displayed to a caller when a generic HTTP status (404 etc) is encountered. If an error message is not defined for the supplied status, the message "HTTP (code)" is returned, e.g. "HTTP 101"
func (*FrameworkErrorGenerator) MessageCode ¶
func (feg *FrameworkErrorGenerator) MessageCode(e FrameworkErrorEvent, a ...interface{}) (message string, code string)
MessageCode returns a message and code for a Framework error event (leaving the caller to create a CategorisedError)
type FrameworkPhase ¶
type FrameworkPhase int
FrameworkPhase is the phase of the request processing during which an error was encountered.
type GraniticHTTPStatusCodeDeterminer ¶
type GraniticHTTPStatusCodeDeterminer struct { NoError int Client int Security int Unexpected int Logic int }
GraniticHTTPStatusCodeDeterminer is the default HTTPStatusCodeDeterminer used by Granitic's XXXWs facilities. The actual HTTP status codes returned can be customised using the fields on this struct. Use NewGraniticHTTPStatusCodeDeterminer() to achieve the default behaviour described in this package's package documentation
func NewGraniticHTTPStatusCodeDeterminer ¶ added in v2.1.0
func NewGraniticHTTPStatusCodeDeterminer() *GraniticHTTPStatusCodeDeterminer
NewGraniticHTTPStatusCodeDeterminer creates a GraniticHTTPStatusCodeDeterminer using the HTTP response codes described in this package's package documentation
func (*GraniticHTTPStatusCodeDeterminer) DetermineCode ¶
func (dhscd *GraniticHTTPStatusCodeDeterminer) DetermineCode(response *Response) int
DetermineCode examines the response and returns an HTTP status code according to the rules defined at the top of this GoDoc page.
type HTTPStatusCodeDeterminer ¶
type HTTPStatusCodeDeterminer interface { // DetermineCode returns the HTTP status code that should be set on the response. DetermineCode(response *Response) int }
HTTPStatusCodeDeterminer implemented by a component able to choose the most appropriate HTTP status code to set given the state of a Response
type Identifier ¶
type Identifier interface { // Identify returns information about the caller derived request and a Context that might be different from the supplied Context. Identify(ctx context.Context, req *http.Request) (iam.ClientIdentity, context.Context) }
Identifier is implemented by components that are able to identify a caller based on a raw HTTP request (normally from headers and cookies). Implementations of this interface may return a new Context that supersedes the supplied Context.
type MarshalingWriter ¶
type MarshalingWriter interface { // MarshalAndWrite converts the data to some serialisable form (JSON, XML etc) and writes it to the HTTP output stream. MarshalAndWrite(data interface{}, w http.ResponseWriter) error }
MarshalingWriter is implemented by components that can convert the supplied data into a form suitable for serialisation and write that serialised form to the HTTP output stream.
type MarshallingResponseWriter ¶
type MarshallingResponseWriter struct { // Injected automatically FrameworkLogger logging.Logger // Component able to calculate the HTTP status code that should be written to the HTTP response. StatusDeterminer HTTPStatusCodeDeterminer // Component able to generate errors if a problem is encountered during marshalling. FrameworkErrors *FrameworkErrorGenerator // The common and static set of headers that should be written to all responses. DefaultHeaders map[string]string // Component able to wrap response data in a standardised structure. ResponseWrapper ResponseWrapper // Component able to dynamically generate additional headers to be written to the response. HeaderBuilder CommonResponseHeaderBuilder // Component able to format services errors in an application specific manner. ErrorFormatter ErrorFormatter // Component able to serialize the data to the HTTP output stream. MarshalingWriter MarshalingWriter // Whether or not the unique ID assigned to the request should be written as a response header IncludeRequestID bool // The header key used if the request ID should be written as a response header RequestIDHeader string }
MarshallingResponseWriter is a response writer that uses automatic marshalling of structs to serialisable forms rather than using templates.
func (*MarshallingResponseWriter) Write ¶
func (rw *MarshallingResponseWriter) Write(ctx context.Context, state *ProcessState, outcome Outcome) error
Write implements ResponseWriter.Write
func (*MarshallingResponseWriter) WriteAbnormalStatus ¶
func (rw *MarshallingResponseWriter) WriteAbnormalStatus(ctx context.Context, state *ProcessState) error
WriteAbnormalStatus implements AbnormalStatusWriter.WriteAbnormalStatus
type Outcome ¶
type Outcome uint
Outcome is an enumeration of the high-level result of processing a request. Used internally.
type ParamBinder ¶
type ParamBinder struct { // Injected by Granitic FrameworkLogger logging.Logger // Source of service errors for errors encountered while binding. FrameworkErrors *FrameworkErrorGenerator }
ParamBinder takes string parameters extracted from an HTTP request, converts them to Go native or Granitic nilable types and injects them into the RequestBody on a Request.
func (*ParamBinder) AutoBindQueryParameters ¶
func (pb *ParamBinder) AutoBindQueryParameters(wsReq *Request)
AutoBindQueryParameters takes the query parameters from an HTTP request and injects them into fields on the Request.RequestBody assuming the parameters have exactly the same name as the target fields. Any errors encountered are recorded as framework errors in the Request.
func (*ParamBinder) BindPathParameters ¶
func (pb *ParamBinder) BindPathParameters(wsReq *Request, p *types.Params)
BindPathParameters takes strings extracted from an HTTP's request path (using regular expression groups) and injects them into fields on the Request.RequestBody. Any errors encountered are recorded as framework errors in the Request.
func (*ParamBinder) BindQueryParameters ¶
func (pb *ParamBinder) BindQueryParameters(wsReq *Request, targets map[string]string)
BindQueryParameters takes the query parameters from an HTTP request and injects them into fields on the Request.RequestBody using the keys of the supplied map as the name of the target fields. Any errors encountered are recorded as framework errors in the Request.
type ProcessState ¶
type ProcessState struct { // The representation of the incoming request at the time processing completed or failed. WsRequest *Request // The representation of the data to be sent to the caller at the time processing completed or failed. WsResponse *Response // The HTTP output stream. HTTPResponseWriter *httpendpoint.HTTPResponseWriter // Errors detected while processing the web service request. If set, supersedes the errors present in Response field. ServiceErrors *ServiceErrors // Information about the caller or user of the web service. Identity iam.ClientIdentity // The HTTP status code to be set on the HTTP response. Status int }
ProcessState is wrapper for current state of request processing. This type is used by components implementing ResponseWriter. Because a request may fail at many points during processing, there is no guarantee that any of the fields in this type are set, valid or complete, so this type must be used with caution.
func NewAbnormalState ¶
func NewAbnormalState(status int, w *httpendpoint.HTTPResponseWriter) *ProcessState
NewAbnormalState creates a new ProcessState for a request that has resulted in an abnormal (HTTP 5xx) outcome).
type Request ¶
type Request struct { // The HTTP method (GET, POST etc) of the underlying HTTP request. HTTPMethod string // If the HTTP request had a body and if the handler that generated this Request implements WsUnmarshallTarget, // then RequestBody will contain a struct representation of the request body. RequestBody interface{} // A copy of the HTTP query parameters from the underlying HTTP request with type-safe accessors. QueryParams *types.Params // Information extracted from the path portion of the HTTP request using regular expression groups with type-safe accessors. PathParams []string // Problems encountered during the parsing and binding phases of request processing. FrameworkErrors []*FrameworkError // Information about the web service caller (if the handler has a Identifier). UserIdentity iam.ClientIdentity // The underlying HTTP request and response (if the handler was configured to pass // this information on). UnderlyingHTTP *DirectHTTPAccess // The component name of the handler that generated this Request. ServingHandler string // The unique ID assigned to this request and stored in the context ID func(ctx context.Context) string // contains filtered or unexported fields }
Request stores information about a web service request that has been either copied in or derived from an underlying HTTP request.
func (*Request) AddFrameworkError ¶
func (wsr *Request) AddFrameworkError(f *FrameworkError)
AddFrameworkError records a framework error.
func (*Request) BoundFields ¶
BoundFields returns the name of all of the names on the RequestBody that were explicitly set by the query/path parameter binding process.
func (*Request) HasFrameworkErrors ¶
HasFrameworkErrors returns true if one or more framework errors have been recorded.
func (*Request) RecordFieldAsBound ¶
RecordFieldAsBound is used to record the fact that a field on the RequestBody was explicitly set by the query/path parameter binding process.
func (*Request) WasFieldBound ¶
WasFieldBound returns true if a field on the RequestBody was explicitly set by the query/path parameter binding process.
type Response ¶
type Response struct { // An instruction that the HTTP status code should be set to this value (if the value is greater than 99). Generally // not set - the response writer will determine the correct status to use. HTTPStatus int // If the web service call resulted in data that should be written as the body of the HTTP response is stored in this field. // Application code must set this field explicitly. Body interface{} // All of the errors encountered while processing this request. Errors *ServiceErrors // Headers that should be set on the HTTP response. Headers map[string]string // If the type of response rendering is template based (e.g. using the XMLWs facility in template mode), this field // can be used to override any default templates or the template associated with the handler that created this response. Template string }
Response contains data that is relevant to the rendering of the result of a web service request to an HTTP response. This type is agnostic of the format (JSON, XML etc) that is to be used to render the response.
func NewResponse ¶
func NewResponse(errorFinder ServiceErrorFinder) *Response
NewResponse creates a valid but empty WsReponse with Errors structure initialised.
type ResponseWrapper ¶
type ResponseWrapper interface {
// WrapResponse takes the supplied body and errors and wraps them in a standardised data structure.
WrapResponse(body interface{}, errors interface{}) interface{}
}
ResponseWrapper is implemented by components able to take the body from an Response and wrap it inside a container that will allow all responses to share a common structure.
type ResponseWriter ¶
type ResponseWriter interface { // Write converts whatever data is present in the supplied state object to the HTTP output stream associated // with the current web service request. Write(ctx context.Context, state *ProcessState, outcome Outcome) error }
ResponseWriter is implemented by components able write the result of a web service call to an HTTP response.
type ServiceErrorCategory ¶
type ServiceErrorCategory int
ServiceErrorCategory indicates the broad 'type' of a service error, used to determine the correct HTTP status code to use.
func CodeToCategory ¶
func CodeToCategory(c string) (ServiceErrorCategory, error)
CodeToCategory takes the short form of a category's name (its first letter, capitialised) an maps that to a ServiceErrorCategory
type ServiceErrorConsumer ¶
type ServiceErrorConsumer interface { // ProvideErrorFinder receives a ServiceErrorFinder ProvideErrorFinder(finder ServiceErrorFinder) }
ServiceErrorConsumer is implemented by components that require a ServiceErrorFinder to be injected into them
type ServiceErrorFinder ¶
type ServiceErrorFinder interface { //Find takes a code and returns the message and category for that error. Behaviour undefined if code is not // recognised. Find(code string) *CategorisedError }
ServiceErrorFinder is implemented by a component that is able to find a message and error category given the code for an error
type ServiceErrors ¶
type ServiceErrors struct { // All services found, in the order in which they occurred. Errors []CategorisedError // An externally computed HTTP status code that reflects the mix of errors in this structure. HTTPStatus int // A component able to find additional information about error from that error's unique code. ErrorFinder ServiceErrorFinder }
ServiceErrors is a structure that records each of the errors found during the processing of a request.
func (*ServiceErrors) AddError ¶
func (se *ServiceErrors) AddError(e *CategorisedError)
AddError records the supplied error.
func (*ServiceErrors) AddNewError ¶
func (se *ServiceErrors) AddNewError(category ServiceErrorCategory, label string, message string)
AddNewError creates a new CategorisedError from the supplied information and captures it.
func (*ServiceErrors) AddPredefinedError ¶
func (se *ServiceErrors) AddPredefinedError(code string, field ...string) error
AddPredefinedError creates a CategorisedError by looking up the supplied code and records that error. If the variadic field parameter is supplied, the created error will be associated with that field name.
func (*ServiceErrors) HasErrors ¶
func (se *ServiceErrors) HasErrors() bool
HasErrors returns true if one or more errors have been encountered and recorded.
type Unmarshaller ¶
type Unmarshaller interface { // Unmarshall deserialises an HTTP request body and converts it to a struct. Unmarshall(ctx context.Context, req *http.Request, wsReq *Request) error }
Unmarshaller is implemented by components that are able to convert an HTTP request body into a struct.
Source Files ¶
Directories ¶
Path | Synopsis |
---|---|
Package handler provides the types used to coordinate the processing of a web service request.
|
Package handler provides the types used to coordinate the processing of a web service request. |
Package json defines types that are specific to handling web service requests and responses as JSON.
|
Package json defines types that are specific to handling web service requests and responses as JSON. |
Package xml defines types that are specific to handling web service requests and responses as XML.
|
Package xml defines types that are specific to handling web service requests and responses as XML. |