I'm working on switching OpenAPI v2 to Open API 3, we'll be using MicroProfile 2.0 with Projects as the plugin that will generate the OAS from the code.
Now, we have different headers that are needed as a kind of authorization. I know I can put them on each resource, that seems just a lot of repetition, so I thought it was a good idea to put in the JaxRSConfiguration file as a #SecurityScheme and add them as security to the #OpenApiDefinition.
#OpenAPIDefinition(
info = #Info(
...
)
),
security = {
#SecurityRequirement(name = Header1),
#SecurityRequirement(name = Header2)
},
components = #Components(
securitySchemes = {
#SecurityScheme( apiKeyName = Header1 ... ) ,
#SecurityScheme( apiKeyName = Header2 ....)
}),
...
)
This is working, however it generates an OR, while it should be an AND (without the - )
security:
- Header1: []
- Header2: []
I thought I could use #SecurityRequirementsSet inside security in the #OpenApiDefinition, but unfortunately this is not allowed. I know I can use it on each call or on top of the class of the different calls but as this is still a sort of repetition, I would prefer to have it as a general authentication security.
Does anybody know how I can achieve this ?
Related
I'm looking into integrating a validation framework to an existing PySpark project. There are a lot of examples how to configure Great Expectations using JSON/YAML files in official documentation. However, in my case table schemas are defined as Python classes and I'm aiming to keep the validation definitions in these classes.
When playing around, I noticed this kind of pattern can be used to validate single expectations without any config files:
spark = SparkSession.builder.master("local[*]").getOrCreate()
df = spark.createDataFrame([
Row(x=1, y="foo"),
Row(x=2, y=None),
])
ds = SparkDFDataset(df)
expectation: ExpectationValidationResult = ds.expect_column_values_to_not_be_null("y")
print(expectation.success)
where expectation.success is either False or True. However, I'm aiming to build expectation suites and generating reports using programmatic configuration but can't find any references how to do it. This is what I tried to hack but it leads to a runtime exception:
ds.append_expectation(ExpectationConfiguration(
expectation_type="expect_column_values_to_not_be_null",
kwargs={'column': 'y', 'result_format': 'BASIC'},
))
engine = SparkDFExecutionEngine(
force_reuse_spark_context=True,
)
validator = Validator(
execution_engine=engine,
expectation_suite=ds.get_expectation_suite(),
)
res = validator.validate()
Any pointers on how to configure Great Expectations without config files (or minimal files) are highly appreciated!
Batches are required for validating expectation suites. Here is a working example:
spark = SparkSession.builder.master("local[*]").getOrCreate()
df = spark.createDataFrame([
Row(x=1, y="foo"),
Row(x=2, y=None),
])
engine = SparkDFExecutionEngine(
force_reuse_spark_context=True,
)
validator = Validator(
execution_engine=engine,
expectation_suite=ExpectationSuite(
expectation_suite_name="my_suite",
expectations=[
ExpectationConfiguration(
expectation_type="expect_column_values_to_not_be_null",
kwargs={"column": "y", "result_format": "BASIC"},
),
ExpectationConfiguration(
expectation_type="expect_column_values_to_not_be_null",
kwargs={"column": "x", "result_format": "BASIC"},
)
]
),
batches=[
Batch(
data=df,
batch_definition=BatchDefinition(
datasource_name="foo",
data_connector_name="foo",
data_asset_name="foo",
batch_identifiers=IDDict(ge_batch_id=str(uuid.uuid1())),
),
),
],
)
res = validator.validate()
I am trying to consume an external REST service. Example:
DATA : lo_client TYPE REF TO if_http_client.
cl_http_client=>create_by_url(
EXPORTING
url = 'http://my_url'
IMPORTING
client = lo_client
EXCEPTIONS
argument_not_found = 1
plugin_not_active = 2
internal_error = 3
OTHERS = 4 ).
DATA(rest_client) = NEW CL_REST_HTTP_CLIENT( lo_client ).
rest_client->GET( ).
GET, POST, PUT and DELETE are Ok since they are implemented in the class CL_REST_HTTP_CLIENT.
Did anyone find a solution to use the PATCH method or how could I consume it otherwise?
PS: the constant for PATCH exists (if_rest_message=>gc_method_patch), but as I said, it's not implemented (send_receive).
Thank you.
You can use CL_HTTP_CLIENT to set method freely, CL_REST_HTTP_CLIENT is also using this class under the hood.
DATA : lo_client TYPE REF TO if_http_client.
cl_http_client=>create_by_url(
EXPORTING
url = 'http://my_url'
IMPORTING
client = lo_client
EXCEPTIONS
argument_not_found = 1
plugin_not_active = 2
internal_error = 3
OTHERS = 4 ).
lo_client->request->set_method( 'PATCH' ).
lo_client->request->set_content_type( 'application/json' ).
lo_client->send( ).
lo_client->receive(
EXCEPTIONS
http_communication_failure = 1
http_invalid_state = 2
http_processing_failed = 3
OTHERS = 4 ).
It's not supported indeed. Quick and dirty way to get it to work is to copy the class and add the following method:
method PATCH.
send_receive( iv_http_method = if_rest_message=>gc_method_patch io_entity = io_entity ).
endmethod.
I am trying to build a REST web service using spyne. So far I have been able to use ComplexModel to represent my resources. Something very basic, like this (borrowed from the examples):
class Meta(ComplexModel):
version = Unicode
description = Unicode
class ExampleService(ServiceBase):
#srpc(_returns=Meta)
def get_meta():
m = Meta()
m.version="2.0"
m.description="Meta complex class example"
return m
application = Application([ExampleService],
tns='sur.factory.webservices',
in_protocol=HttpRpc(validator='soft'),
out_protocol=JsonDocument()
)
if __name__ == '__main__':
wsgi_app = WsgiApplication(application)
server = make_server('0.0.0.0', 8000, wsgi_app)
server.serve_forever()
To run I use curl -v "http://example.com:8000/get_meta" and I get what I expect.
But what if I would like to access some hierarchy of resources like http://example.com:8000/resourceA/get_meta ??
Thanks for your time!
Two options: Static and dynamic. Here's the static one:
from spyne.util.wsgi_wrapper import WsgiMounter
app1 = Application([SomeService, ...
app2 = Application([SomeOtherService, ...
wsgi_app = WsgiMounter({
'resourceA': app1,
'resourceB': app2,
})
This works today. Note that you can stack WsgiMounter's.
As for the dynamic one, you should use HttpPattern(). I consider this still experimental as I don't like the implementation, but this works with 2.10.x, werkzeug, pyparsing<2 and WsgiApplication:
class ExampleService(ServiceBase):
#rpc(Unicode, _returns=Meta, _patterns=[HttpPattern("/<resource>/get_meta")])
def get_meta(ctx, resource):
m = Meta()
m.version = "2.0"
m.description="Meta complex class example with resource %s" % resource
return m
Don't forget to turn on validation and put some restrictions on the resource type to prevent DoS attacks and throwing TypeErrors and whatnot. I'd do:
ResourceType = Unicode(24, min_len=3, nullable=False,
pattern="[a-zA-Z0-9]+", type_name="ResourceType")
Note that you can also match http verbs with HttpPattern. e.g.
HttpPattern("/<resource>/get_meta", verb='GET')
or
HttpPattern("/<resource>/get_meta", verb='(PUT|PATCH)')
Don't use host matching, as of 2.10, it's broken.
Also, as this bit of Spyne is marked as experimental, its api can change any time.
I hope this helps
I would like to increase the MaxBufferSize, MaxBufferPoolSize, ReceivedMessageSize, along with the readerQuotas maxDepth="2147483646" maxStringContentLength="2147483646" maxArrayLength="2147483646" maxBytesPerRead="2147483646" maxNameTableCharCount="2147483646", It is my understanding that I must change these parameters in the registration process. But I see no examples anywhere on doing this.
I would appreciate any help on this matter.
Don't know if you found an answer to this or not but it would look something like this:
builder.Register(
container =>
new ChannelFactory<TService>(
new WSHttpBinding { TransactionFlow = supportTransactionFlow,
MaxReceivedMessageSize = 2147483646,
ReaderQuotas = {
MaxStringContentLength = 2147483646,
MaxDepth = 2147483646,
MaxArrayLength= 2147483646 }},
endpointAddress)).InstancePerDependency();
I have been looking at a couple of books and resources on domain specific languages.
I think I want to build an internal DSL in Scala.
def instrument = new FXInstrument {
provider = "EuroBase"
instrumentOrders = List(
new FXOrder {
baseCcy = "GBP"
termCcy = "EUR"
legs = List(
new FXLeg {
amountPrice = 100000.0
spotPrice = 1.56
requirements = List(
new FXRequirement {
baseCcy="GBP" termCcy="EUR"
settlement="Banker Rain"
}
)
},
new FXLeg {
amountPrice = 200000.0
spotPrice = 1.50
requirements = List(
new FXRequirement {
baseCcy="GBP" termCcy="EUR"
settlement="Banker Sunny"
}
)
}
)
}
}
Such that following asserts are valid:
instrument.orders(0).baseCcy should equal ("GBP")
instrument.orders(0).termCcy should equal ("EUR")
instrument.orders(0).legs(0).amountPrice should equal 100000.0
instrument.orders(0).legs(0).spotPrice should equal 1.56
instrument.orders(0).legs(1).amountPrice should equal 200000.0
instrument.orders(0).legs(1).spotPrice should equal 1.50
instrument.orders(0).legs(0).requirements(0).settlement should equal "Banker Rain"
instrument.orders(0).legs(1).requirements(0).settlement should equal "Banker Sunny"
I just do not know quite how to implement the domain specific language as an internal representation
1) new FXOrder() { /closure/ }
I like this syntax, is it good or should I prefer companion objects.
For instance I can quickly introduce other FX types easy.
2) I want to use "peers" such FXOrder is a scala.Proxy mixee, thus it uses the trait Proxy (mixin)
For example ``instrument.peer'' gives the internal peer Java Object of the third party proprietary API (a well known financial services trading system, can you guess?)
Ditto for
instrument.orders(0).peer
instrument.orders(0).legs(0).peer
instrument.orders(0).legs(0).requirements(0).peer
and so on.
I realise that domain specific language is not as simple as I thought, however some pointers on this above, would be really be useful. I would appreciate your responses. Ta!
PP
I haven't considered what you want yet, but I saw a problem:
1) new FXOrder() { /closure/ }
No, it doesn't work that way. When you follow an initialization (new Something) with a block, you are doing anonymous subclassing. What you are actually doing is new FXOrder() { /constructor, methods, getters and setters/ }.
Maybe, this can help you: DSL in Scala