PACT-JS - Provider contract verification error/failure - PactFlow - api

I am pulling my hair out. I have created a Pact-JS test framework to test my simple NodeJS application. I will show all the code below. I have used PactFlow to host my contract document (which was generated by running my consumer test). The problem is When I run my provider code it is failing. I get the following error (I will post the more verbose error below)) - `assert_success!': Error retrieving https://zaizi.pactflow.io/pacts/provider/Clients%20Service/for-verification status=404
Consumer test code - pact.consumer.spec.js
const { Matchers, Publisher } = require("#pact-foundation/pact")
const Pact = require("#pact-foundation/pact").Pact
const { getClients, getClient, postClient } = require("../../src/consumer")
const path = require("path")
// mock provider setup
const mockProvider = new Pact({
port: 8081,
log: path.resolve(process.cwd(), "__tests__/logs", "mock-provider.log"), // log file location and name
dir: path.resolve(process.cwd(), "__tests__/pacts"), // location where pact contract will be saved
spec: 2,
logLevel: 'INFO',
pactfileWriteMode: "overwrite",
consumer: "pact-consumer",
provider: "pact-provider"
})
describe("Pact for Clients Service API", () => {
beforeAll(() => mockProvider.setup()); // Start the Mock Server and wait for it to be available
afterEach(() => mockProvider.verify()); // Verifies that all interactions specified
afterAll(() => mockProvider.finalize()); // Records the interactions between the Mock Server into the pact file and shuts it down
describe('given there are clients', () => {
describe('when a request is made to GET all clients', () => {
// GET_EXPECTED_BODY = [
// { "firstName": "Lisa", "lastName": "Simpson", "age": 8, "id": 1 },
// { "firstName": "Wonder", "lastName": "Woman", "age": 30, "id": 2 },
// { "firstName": "Homer", "lastName": "Simpson", "age": 39, "id": 3 }]
const GET_EXPECTED_BODY = [{
"firstName": "Lisa",
"lastName": "Simpson",
"age": 8,
"id": 1
},
{
"firstName": "Wonder",
"lastName": "Woman",
"age": 30,
"id": 2
},
{
"firstName": "Homer",
"lastName": "Simpson",
"age": 39,
"id": 3
}]
beforeEach(() => {
const interaction = {
state: "i have a list of clients",
uponReceiving: "a request for all clients",
withRequest: {
method: "GET",
path: "/clients",
headers: {
Accept: "application/json, text/plain, */*",
},
},
willRespondWith: {
status: 200,
headers: {
"Content-Type": "application/json; charset=utf-8",
},
body: GET_EXPECTED_BODY,
},
}
return mockProvider.addInteraction(interaction)
})
it('will return a list of clients', async() => {
// make request to the Pact mock server to get all clients
const response = await getClients()
expect(response.headers['content-type']).toBe("application/json; charset=utf-8")
expect(response.data).toEqual(GET_EXPECTED_BODY)
expect(response.status).toEqual(200)
})
})
})
})
Provider test code - pact.provider.spec.js
const path = require("path")
const { Verifier } = require("#pact-foundation/pact")
const { server, importData } = require("../../src/provider")
require('dotenv').config()
jest.setTimeout(30000);
describe("Clients Service Pact verification", () => {
const port = 8081
let opts = {
provider: "Clients Service",
logLevel: "DEBUG",
providerBaseUrl: `http://localhost:${port}`,
// pactUrls: [path.resolve(process.cwd(), "./__tests__/pacts/pact-consumer-pact-provider.json")],
pactBrokerUrl: process.env.PACT_BROKER_BASE_URL,
pactBrokerToken: process.env.PACT_BROKER_TOKEN,
consumerVersionTags: ["pact-consumer"],
providerVersionTags: ["pact-provider"],
publishVerificationResult: false,
providerVersion: "1.0.0"
}
// Start real provider server
beforeAll(async () => {
server.listen(port, () => {
importData()
console.log(`Provider listening on http://localhost:${port}`)
})
})
it("validates the expectations of the clients service", () => {
return new Verifier(opts).verifyProvider().then(output => {
console.log("Pact Verification Complete!")
console.log(output)
})
})
afterAll(async ()=> {
server.close();
})
// it('should validate the expectations of Order Web', () => {
// return new Verifier().verifyProvider(opts)
// })
})
My pact contract is here:-
{
"consumer": {
"name": "pact-consumer"
},
"provider": {
"name": "pact-provider"
},
"interactions": [
{
"description": "a request for all clients",
"providerState": "i have a list of clients",
"request": {
"method": "GET",
"path": "/clients",
"headers": {
"Accept": "application/json, text/plain, */*"
}
},
"response": {
"status": 200,
"headers": {
"Content-Type": "application/json; charset=utf-8"
},
"body": [
{
"firstName": "Lisa",
"lastName": "Simpson",
"age": 8,
"id": 1
},
{
"firstName": "Wonder",
"lastName": "Woman",
"age": 30,
"id": 2
},
{
"firstName": "Homer",
"lastName": "Simpson",
"age": 39,
"id": 3
}
]
}
}
],
"metadata": {
"pactSpecification": {
"version": "2.0.0"
}
}
}
This is my PactFlow:-
Verbose Error log:-
[2022-04-13 16:57:12.453 +0000] INFO (15316 on DESKTOP-TJVM91P): pact#9.17.3: Verifying provider
console.log
Provider listening on http://localhost:8081
at Server.<anonymous> (__tests__/provider/pact.provider.spec.js:28:21)
[2022-04-13 16:57:12.481 +0000] INFO (15316 on DESKTOP-TJVM91P): pact-node#10.17.2: Verifying Pacts.
[2022-04-13 16:57:12.483 +0000] INFO (15316 on DESKTOP-TJVM91P): pact-node#10.17.2: Verifying Pact Files
[2022-04-13 16:57:12.484 +0000] DEBUG (15316 on DESKTOP-TJVM91P): pact-node#10.17.2: Starting pact binary 'D:\p\pact-nodejs-demo\node_modules\#pact-foundation\pact-node\standalone\win32-1.88.83\pact\bin\pact-provider-verifier.bat', with arguments [--provider-states-setup-url http://localhost:59761/_pactSetup --provider Clients Service --log-level DEBUG --provider-base-url http://localhost:59761 --pact-broker-base-url https://******.pactflow.io --broker-token 1iB-FQbUuvpxce6QX-DBTQ --consumer-version-tag pact-consumer --provider-version-tag pact-provider --publish-verification-results false --provider-app-version 1.0.0 --verbose true]
[2022-04-13 16:57:12.491 +0000] DEBUG (15316 on DESKTOP-TJVM91P): pact-node#10.17.2: Created 'D:\p\pact-nodejs-demo\node_modules\#pact-foundation\pact-node\standalone\win32-1.88.83\pact\bin\pact-provider-verifier.bat' process with PID: 10524
FAIL __tests__/provider/pact.provider.spec.js (9.938s)
Clients Service Pact verification
× validates the expectations of the clients service (8022ms)
● Clients Service Pact verification › validates the expectations of the clients service
D:/p/pact-nodejs-demo/node_modules/#pact-foundation/pact-node/standalone/win32-1.88.83/pact/lib/vendor/ruby/2.2.0/gems/pact-1.62.0/lib/pact/hal/entity.rb:102:in `assert_success!': Error retrieving https://******.pactflow.io/pacts/provider/Clients%20Service/for-verification status=404 (Pact::Hal::ErrorResponseReturned)
from D:/p/pact-nodejs-demo/node_modules/#pact-foundation/pact-node/standalone/win32-1.88.83/pact/lib/vendor/ruby/2.2.0/gems/pact-1.62.0/lib/pact/hal/link.rb:65:in `post!'
from D:/p/pact-nodejs-demo/node_modules/#pact-foundation/pact-node/standalone/win32-1.88.83/pact/lib/vendor/ruby/2.2.0/gems/pact-1.62.0/lib/pact/pact_broker/fetch_pact_uris_for_verification.rb:75:in `pacts_for_verification_entity'
from D:/p/pact-nodejs-demo/node_modules/#pact-foundation/pact-node/standalone/win32-1.88.83/pact/lib/vendor/ruby/2.2.0/gems/pact-1.62.0/lib/pact/pact_broker/fetch_pact_uris_for_verification.rb:61:in `pacts_for_verification'
from D:/p/pact-nodejs-demo/node_modules/#pact-foundation/pact-node/standalone/win32-1.88.83/pact/lib/vendor/ruby/2.2.0/gems/pact-1.62.0/lib/pact/pact_broker/fetch_pact_uris_for_verification.rb:44:in `call'
from D:/p/pact-nodejs-demo/node_modules/#pact-foundation/pact-node/standalone/win32-1.88.83/pact/lib/vendor/ruby/2.2.0/gems/pact-1.62.0/lib/pact/pact_broker/fetch_pact_uris_for_verification.rb:38:in `call'
from D:/p/pact-nodejs-demo/node_modules/#pact-foundation/pact-node/standalone/win32-1.88.83/pact/lib/vendor/ruby/2.2.0/gems/pact-1.62.0/lib/pact/pact_broker.rb:18:in `fetch_pact_uris_for_verification'
from D:/p/pact-nodejs-demo/node_modules/#pact-foundation/pact-node/standalone/win32-1.88.83/pact/lib/vendor/ruby/2.2.0/gems/pact-provider-verifier-1.36.1/lib/pact/provider_verifier/aggregate_pact_configs.rb:46:in `pacts_for_verification'
from D:/p/pact-nodejs-demo/node_modules/#pact-foundation/pact-node/standalone/win32-1.88.83/pact/lib/vendor/ruby/2.2.0/gems/pact-provider-verifier-1.36.1/lib/pact/provider_verifier/aggregate_pact_configs.rb:39:in `pacts_urls_from_broker'
from D:/p/pact-nodejs-demo/node_modules/#pact-foundation/pact-node/standalone/win32-1.88.83/pact/lib/vendor/ruby/2.2.0/gems/pact-provider-verifier-1.36.1/lib/pact/provider_verifier/aggregate_pact_configs.rb:26:in `call'
from D:/p/pact-nodejs-demo/node_modules/#pact-foundation/pact-node/standalone/win32-1.88.83/pact/lib/vendor/ruby/2.2.0/gems/pact-provider-verifier-1.36.1/lib/pact/provider_verifier/aggregate_pact_configs.rb:10:in `call'
from D:/p/pact-nodejs-demo/node_modules/#pact-foundation/pact-node/standalone/win32-1.88.83/pact/lib/vendor/ruby/2.2.0/gems/pact-provider-verifier-1.36.1/lib/pact/provider_verifier/app.rb:211:in `all_pact_urls'
from D:/p/pact-nodejs-demo/node_modules/#pact-foundation/pact-node/standalone/win32-1.88.83/pact/lib/vendor/ruby/2.2.0/gems/pact-provider-verifier-1.36.1/lib/pact/provider_verifier/app.rb:225:in `warn_empty_pact_set'
from D:/p/pact-nodejs-demo/node_modules/#pact-foundation/pact-node/standalone/win32-1.88.83/pact/lib/vendor/ruby/2.2.0/gems/pact-provider-verifier-1.36.1/lib/pact/provider_verifier/app.rb:40:in `call'
from D:/p/pact-nodejs-demo/node_modules/#pact-foundation/pact-node/standalone/win32-1.88.83/pact/lib/vendor/ruby/2.2.0/gems/pact-provider-verifier-1.36.1/lib/pact/provider_verifier/app.rb:35:in `call'
from D:/p/pact-nodejs-demo/node_modules/#pact-foundation/pact-node/standalone/win32-1.88.83/pact/lib/vendor/ruby/2.2.0/gems/pact-provider-verifier-1.36.1/lib/pact/provider_verifier/cli/verify.rb:49:in `verify'
from D:/p/pact-nodejs-demo/node_modules/#pact-foundation/pact-node/standalone/win32-1.88.83/pact/lib/vendor/ruby/2.2.0/gems/thor-1.2.1/lib/thor/command.rb:27:in
`run'
from D:/p/pact-nodejs-demo/node_modules/#pact-foundation/pact-node/standalone/win32-1.88.83/pact/lib/vendor/ruby/2.2.0/gems/thor-1.2.1/lib/thor/invocation.rb:127:in `invoke_command'
from D:/p/pact-nodejs-demo/node_modules/#pact-foundation/pact-node/standalone/win32-1.88.83/pact/lib/vendor/ruby/2.2.0/gems/thor-1.2.1/lib/thor.rb:392:in `dispatch'
from D:/p/pact-nodejs-demo/node_modules/#pact-foundation/pact-node/standalone/win32-1.88.83/pact/lib/vendor/ruby/2.2.0/gems/thor-1.2.1/lib/thor/base.rb:485:in `start'
from D:/p/pact-nodejs-demo/node_modules/#pact-foundation/pact-node/standalone/win32-1.88.83/pact/lib/vendor/ruby/2.2.0/gems/pact-provider-verifier-1.36.1/lib/pact/provider_verifier/cli/custom_thor.rb:17:in `start'
from D:/p/pact-nodejs-demo/node_modules/#pact-foundation/pact-node/standalone/win32-1.88.83/pact/lib/app/pact-provider-verifier.rb:33:in `<main>'
opening connection to ******.pactflow.io:443...
opened
starting SSL for ******.pactflow.io:443...
SSL established
<- "GET / HTTP/1.1\r\nAccept-Encoding: gzip;q=1.0,deflate;q=0.6,identity;q=0.3\r\nAccept: application/hal+json\r\nUser-Agent: Ruby\r\nAuthorization: [redacted]\r\n"
-> "HTTP/1.1 200 OK\r\n"
-> "Date: Wed, 13 Apr 2022 16:57:19 GMT\r\n"
-> "Content-Type: application/hal+json;charset=utf-8\r\n"
-> "Content-Length: 5555\r\n"
-> "Connection: keep-alive\r\n"
-> "Vary: Accept\r\n"
-> "Server: Webmachine-Ruby/1.6.0 Rack/1.3\r\n"
-> "X-Pact-Broker-Version: 2.98.0\r\n"
-> "X-Pact-Broker-Git-Sha: 3a08d128\r\n"
-> "X-Pactflow-Git-Sha: 85e7754e3\r\n"
-> "X-Content-Type-Options: nosniff\r\n"
-> "Strict-Transport-Security: max-age=63072000; includeSubDomains; preload\r\n"
-> "X-Request-Id: cb35bba1d72c207abc7d787cbb5f4473\r\n"
-> "\r\n"
reading 5555 bytes...
-> "{\"_links\":{\"self\":{\"href\":\"https://******.pactflow.io\",\"title\":\"Index\",\"templated\":false},\"pb:publish-pact\":{\"href\":\"https://******.pactflow.io/pacts/provider/{provider}/consumer/{consumer}/version/{consumerApplicationVersion}\",\"title\":\"Publish a pact\",\"templated\":true},\"pb:publish-contracts\":{\"href\":\"https://******.pactflow.io/contracts/publish\",\"title\":\"Publish contracts\",\"templated\":false},\"pb:latest-pact-versions\":{\"href\":\"https://******.pactflow.io/pacts/latest\",\"title\":\"Latest pact versions\",\"templated\":false},\"pb:tagged-pact-versions\":{\"href\":\"https://******.pactflow.io/pacts/provider/{provider}/consumer/{consumer}/tag/{tag}\",\"title\":\"All versions of a pact for a given consumer, provider and consumer version tag\",\"templated\":false},\"pb:pacticipants\":{\"href\":\"https://******.pactflow.io/pacticipants\",\"title\":\"Pacticipants\",\"templated\":false},\"pb:pacticipant\":{\"href\":\"https://******.pactflow.io/pacticipants/{pacticipant}\",\"title\":\"Fetch pacticipant by name\",\"templated\":true},\"pb:latest-provider-pacts\":{\"href\":\"https://******.pactflow.io/pacts/provider/{provider}/latest\",\"title\":\"Latest pacts by provider\",\"templated\":true},\"pb:latest-provider-pacts-with-tag\":{\"href\":\"https://******.pactflow.io/pacts/provider/{provider}/latest/{tag}\",\"title\":\"Latest pacts for provider with the specified tag\",\"templated\":true},\"pb:provider-pacts-with-tag\":{\"href\":\"https://******.pactflow.io/pacts/provider/{provider}/tag/{tag}\",\"title\":\"All pact versions for the provider with the specified consumer version tag\",\"templated\":true},\"pb:provider-pacts\":{\"href\":\"https://******.pactflow.io/pacts/provider/{provider}\",\"title\":\"All pact versions for the specified provider\",\"templated\":true},\"pb:latest-version\":{\"href\":\"https://******.pactflow.io/pacticipants/{pacticipant}/latest-version\",\"title\":\"Latest pacticipant version\",\"templated\":true},\"pb:latest-tagged-version\":{\"href\":\"https://******.pactflow.io/pacticipants/{pacticipant}/latest-version/{tag}\",\"title\":\"Latest pacticipant version with the specified tag\",\"templated\":true},\"pb:webhooks\":{\"href\":\"https://******.pactflow.io/webhooks\",\"title\":\"Webhooks\",\"templated\":false},\"pb:webhook\":{\"href\":\"https://******.pactflow.io/webhooks/{uuid}\",\"title\":\"Webhook\",\"templated\":true},\"pb:integrations\":{\"href\":\"https://******.pactflow.io/integrations\",\"title\":\"Integrations\",\"templated\":false},\"pb:pacticipant-version-tag\":{\"href\":\"https://******.pactflow.io/pacticipants/{pacticipant}/versions/{version}/tags/{tag}\",\"title\":\"Get, create or delete a tag for a pacticipant version\",\"templated\":true},\"pb:pacticipant-branch-version\":{\"href\":\"https://******.pactflow.io/pacticipants/{pacticipant}/branches/{branch}/versions/{version}\",\"title\":\"Get or add/create a pacticipant version for a branch\",\"templated\":true},\"pb:pacticipant-version\":{\"href\":\"https://******.pactflow.io/pacticipants/{pacticipant}/versions/{version}\",\"title\":\"Get, create or delete a pacticipant version\",\"templated\":true},\"pb:metrics\":{\"href\":\"https://******.pactflow.io/metrics\",\"title\":\"Get Pact Broker metrics\"},\"pb:can-i-deploy-pacticipant-version-to-tag\":{\"href\":\"https://******.pactflow.io/can-i-deploy?pacticipant={pacticipant}\\u0026version={version}\\u0026to={tag}\",\"title\":\"Determine if an application version can be safely deployed to an environment identified by the given tag\",\"templated\":true},\"pb:can-i-deploy-pacticipant-version-to-environment\":{\"href\":\"https://******.pactflow.io/can-i-deploy?pacticipant={pacticipant}\\u0026version={version}\\u0026environment={environment}\",\"title\":\"Determine if an application version can be safely deployed to an environment\",\"templated\":true},\"pb:provider-pacts-for-verification\":{\"href\":\"https://******.pactflow.io/pacts/provider/{provider}/for-verification\",\"title\":\"Pact versions to be verified for the specified provider\",\"templated\":true},\"beta:provider-pacts-for-verification\":{\"name\":\"beta\",\"href\":\"https://******.pactflow.io/pacts/provider/{provider}/for-verification\",\"title\":\"DEPRECATED - please use pb:provider-pacts-for-verification\",\"templated\":true},\"curies\":[{\"name\":\"pb\",\"href\":\"https://******.pactflow.io/doc/{rel}?context=index\",\"templated\":true},{\"name\":\"beta\",\"href\":\"https://******.pactflow.io/doc/{rel}?context=index\",\"templated\":true}],\"pb:environments\":{\"title\":\"Environments\",\"href\":\"https://******.pactflow.io/environments\",\"templated\":false},\"pb:environment\":{\"title\":\"Environment\",\"href\":\"https://******.pactflow.io/environments/{uuid}\",\"templated\":true},\"pb:api-tokens\":{\"href\":\"https://******.pactflow.io/settings/tokens\",\"title\":\"API tokens\",\"templated\":false},\"pb:audit\":{\"href\":\"https://******.pactflow.io/audit\",\"title\":\"Audit trail\",\"templated\":false},\"pb:secrets\":{\"href\":\"https://******.pactflow.io/secrets\",\"title\":\"Secrets\",\"templated\":false},\"pf:admin-users\":{\"href\":\"https://******.pactflow.io/admin/users\",\"title\":\"Users\",\"templated\":false},\"pf:admin-teams\":{\"href\":\"https://******.pactflow.io/admin/teams\",\"title\":\"Teams\",\"templated\":false},\"pf:admin-system-accounts\":{\"href\":\"https://******.pactflow.io/admin/system-accounts\",\"title\":\"System accounts\",\"templated\":false},\"pf:admin-roles\":{\"href\":\"https://******.pactflow.io/admin/roles\",\"title\":\"Roles\",\"templated\":false},\"pf:admin-permissions\":{\"href\":\"https://******.pactflow.io/admin/permissions\",\"title\":\"Permissions\",\"templated\":false},\"pf:admin-authentication-settings\":{\"href\":\"https://******.pactflow.io/admin/tenant/authentication-settings\",\"title\":\"Authentication Settings\",\"templated\":false},\"pf:user-allocations\":{\"href\":\"https://******.pactflow.io/tenant/limits\",\"title\":\"User Allocations\",\"templated\":false}}}"

It's quite simple. You have defined the provider in you consumer test (and what's in the contract) as pact-provider.
In your provider test, however, it is called Clients Service.
When your provider test is trying to discover the contracts, it uses the provider name as the key. Because there is no provider called Clients Service it's getting a a 404.
Either
Update the provider name in the consumer to to Clients Service (and delete the old integration)
Update the provider name to pact-provider
(1. seems like the right thing to do)

Related

RabbitMQ/Krakend/NestJS - How can I post the consumed message through Krakend API's async agent?

This is my config for krakend.json
"async_agent": [
{
"name": "test-agent",
"connection": {
"max_retries": 10,
"backoff_strategy": "exponential-jitter"
},
"consumer": {
"topic": "krakend",
"workers": 5
},
"backend": [
{
"url_pattern": "/greeted",
"method": "POST",
"host": [ "http://127.0.0.1:2999" ],
"disable_host_sanitize": false
}
],
"extra_config": {
"async/amqp": {
"host": "amqp://guest:guest#localhost:5672/",
"name": "krakend",
"exchange": "ApiGatewayExchange",
"durable": true,
"delete": false,
"exclusive": false,
"no_wait": false,
"auto_ack": false
}
}
}
]
Messages are sent from service-a like so:
export class AppService {
constructor(#Inject('GREETING_SERVICE') private client: ClientProxy){}
getHello(): ResponseDTO {
const responseDTO: ResponseDTO = {
action: 'Hello',
service: 'from service A'
}
this.client.emit('', responseDTO);
return responseDTO;
}
}
And imported GREETING_SERVICE config like so:
imports: [
ClientsModule.register([
{
name: 'GREETING_SERVICE',
transport: Transport.RMQ,
options: {
urls: ['amqp://test:test#localhost:5672/'],
queue: 'krakend'
}
}
])
],
Lastly, this is the endpoint in another service (let's call this service-c) that gets that message from the consumer:
#Post('greeted')
TestHello(#Body() data: any) {
console.log(data)
return data
}
The message is successfully consumed as set by the async_agent in my krakend file, but the message isn't posted as a body to that endpoint. When I did a console.log of that data supposedly passed, it just prints {}.
Am I doing anything wrong here? Been scratching my head for hours.
The async part of your krakend.json configuration looks good to me, but I am suspecting about the problem you might have.
Most of the javascript frameworks today will require you to pass specific headers to work their magic like Content-Type or Accept. You have to take into account that KrakenD will pass a very reduced set of headers to your NestJS application (Accept-Encoding and User-Agent as far as I can remember).
I am unfamiliar with NestJS, but I would bet that you need to pass the Content-Type and you are good to go. Here's my suggestion of configuration:
"async_agent": [
{
"name": "test-agent",
"connection": {
"max_retries": 10,
"backoff_strategy": "exponential-jitter"
},
"consumer": {
"topic": "krakend",
"workers": 5
},
"backend": [
{
"url_pattern": "/greeted",
"method": "POST",
"host": [
"http://127.0.0.1:2999"
],
"disable_host_sanitize": false,
"extra_config": {
"modifier/martian": {
"header.Modifier": {
"scope": [
"request"
],
"name": "Content-Type",
"value": "application/json"
}
}
}
}
],
"extra_config": {
"async/amqp": {
"host": "amqp://guest:guest#localhost:5672/",
"name": "krakend",
"exchange": "ApiGatewayExchange",
"durable": true,
"delete": false,
"exclusive": false,
"no_wait": false,
"auto_ack": false
}
}
}
]
}
Hope this helps

Check that JSON value has a string that matches certain values in Postman

I'm trying to write tests to see if a service is OK, Unknown, or Unreachable via my API. However, all of my tests come back as having passed. I know that all my servers are in an "OK" state, though, and that none of them are "Unreachable" or "Unknown." I believe the "unknown" and "unreachable" tests should be failing. What am I doing wrong?
Here's the body of the response:
{
"result": {
"dhcpServers": [
{
"ref": "DHCPServers/4",
"name": "unixdns",
"address": "10.9.0.220",
"resolvedAddress": "10.9.0.220",
"username": "",
"password": "",
"type": "ISC",
"state": "OK",
"security": "Unknown",
"customProperties": {},
"enabled": true,
"dhcpv6": false
},
{
"ref": "DHCPServers/15",
"name": "mmappliance",
"address": "10.9.0.156",
"resolvedAddress": "10.9.0.156",
"username": "",
"password": "",
"type": "ISC",
"state": "OK",
"security": "Unknown",
"customProperties": {},
"enabled": true,
"dhcpv6": false
},
{
"ref": "DHCPServers/19",
"name": "WIN-51",
"proxy": "10.9.0.150",
"address": "10.9.0.150",
"resolvedAddress": "10.9.0.150",
"username": "",
"password": "",
"type": "MSDHCP",
"state": "OK",
"security": "Unknown",
"customProperties": {},
"enabled": true,
"dhcpv6": true
},
{
"ref": "DHCPServers/22",
"name": "WIN-PM",
"proxy": "10.9.0.100",
"address": "10.9.0.100",
"resolvedAddress": "10.9.0.100",
"username": "",
"password": "",
"type": "MSDHCP",
"state": "OK",
"security": "Unknown",
"customProperties": {},
"enabled": true,
"dhcpv6": true
}
],
"totalResults": 4
}
}
I've written the following tests:
let jsonData = pm.response.json()
pm.test('DHCP service is ok', () => {
_.each(jsonData.dhcpServers, (item) => {
pm.expect(item.state).to.have.body('OK')
})
})
pm.test('DHCP service is Unknown', () => {
_.each(jsonData.dhcpServers, (item) => {
pm.expect(item.state).to.have.body('Unknown')
})
})
pm.test('DHCP service is unreachable', () => {
_.each(jsonData.dhcpServers, (item) => {
pm.expect(item.state).to.have.body('Unreachable')
})
})
//Unknown - DHCP Server Controller status is unknown.
//OK - DHCP Server Controller and service are both OK.
//Unreachable - DHCP Server Controller is offline or otherwise unreachable.
//Out of date - DHCP Server Controller has a different version than Central.
//Updating - DHCP Server Controller version is being updated.
//Uninitialized - DHCP Server is on a uninitialized appliance that needs to be manually initialized.
//Detached - DHCP Server has been detached without removing it from the system.
//DHCP Service Down - DHCP Server service is down and DNS server is not responding to queries.
//DHCP Service Impaired - DHCP Server service is running but impaired.
You miss one level to get dhcpServers. It should be jsonData.result.dhcpServers, not jsonData.dhcpServers,
Use .eql('OK') instead of .to.have.body('OK')
The test would be:
pm.test('DHCP service is ok', () => {
_.each(jsonData.result.dhcpServers, (item) => {
pm.expect(item.state).eql('OK');
})
})

React native sending image to server using formdata

I have a problem sending a picture to a server, that's like the default approach, but it does not seem to work.
var source = '/Users/alexx/Library/Developer/CoreSimulator/Devices/44F0FA92-4898-4CFB-862E-4E5EC4C8AB28/data/Containers/Bundle/Application/34BCE695-4B4F-472F-AB5C-F2336AC45273/DoorLock.app/123.jpg';
const form = new FormData();
form.append('image', {
uri: source,
type: 'image/jpg',
name: '123.jpg',
});
const data = () => {
fetch(api ,{
method: 'POST',
body: form,
})
that's the response i get from the server:
{
"_bodyBlob": {
"_data": {
"__collector": [
Object
],
"blobId": "78B18938-15BF-4F18-B3C8-1EB30A24D9F8",
"name": "test.html",
"offset": 0,
"size": 192,
"type": "text/html"
}
},
"_bodyInit": {
"_data": {
"__collector": [
Object
],
"blobId": "78B18938-15BF-4F18-B3C8-1EB30A24D9F8",
"name": "test.html",
"offset": 0,
"size": 192,
"type": "text/html"
}
},
"bodyUsed": false,
"headers": {
"map": {
"connection": "keep-alive",
"content-length": "192",
"content-type": "text/html",
"date": "Mon, 02 Nov 2020 22:57:21 GMT",
"server": "PythonAnywhere"
}
},
"ok": false,
"status": 400,
"statusText": undefined,
"type": "default",
"url": api
}
Although this python code works perfectly and gets a correct response
img = {'file':('123.png', open('the path to the pic/123.png', 'rb'), 'image/png)}
post(api, files = img)
is there any way to get this working or its the server side problem that can't receive the correct arguments?
Adding "file://" to the beginning of the source string fixed the problem.
so the src looks like
var source = 'file:///Users/alexx/Library/Developer/CoreSimulator/Devices/44F0FA92-4898-4CFB-862E-4E5EC4C8AB28/data/Containers/Bundle/Application/34BCE695-4B4F-472F-AB5C-F2336AC45273/DoorLock.app/123.jpg';
then it fetches perfectly, hope it helps anybody who tries to send a local image using formdata, the summary looks like this now
const form = new FormData();
form.append('file', {
uri: source,
name: '123.jpg',
fileName: 'file', //optional
});
fetch(uri,{
method: 'post',
body: form,
})
.then(response => {
console.log("image uploaded")
console.log(response)
})
.catch(console.log);
In Formdata when you pass files, you need to pass 3 parameters where
key expected from the backend (in your case image).
It will be an object which has three properties named name, type, and uri where type is the mime type (ex: image/jpeg).
name of the file
Eg:
data.append("FilePath",{
name:"image.png",
type:"image/png",
uri:"content://com.camera/image.png"
},image.png)

AddInMemoryClients results in Unknown client or not enabled

I'm trying to get Identity server 4 to work in an ASP Net Core 3 application with an Angular 8 SPA using "oidc-client": "1.10.1".
If I add the following to my appsettings.json
"IdentityServer": {
"Key": {
"Type": "File",
"FilePath": "acertificate.pfx",
"Password": "notmyrealpassword..orisit?"
},
"Clients": {
"dev-client": {
"Profile": "IdentityServerSPA",
}
}
}
Using this client:
{
authority: 'https://localhost:5001/',
client_id: 'dev-client',
redirect_uri: 'http://localhost:4200/auth-callback',
post_logout_redirect_uri: 'http://localhost:4200/',
response_type: 'id_token token',
scope: 'openid profile API',
filterProtocolClaims: true,
loadUserInfo: true
}
I get: Invalid redirect_uri: http://localhost:4200/auth-callback
adding.
"dev-client": {
"Profile": "IdentityServerSPA",
"RedirectUris": [ "http://localhost:4200/auth-callback" ]
}
does nothing. If I add the Client config copied (almost) from the documentation
"Clients": [
{
"Enabled": true,
"ClientId": "dev-client",
"ClientName": "Local Development",
"AllowedGrantTypes": [ "implicit" ],
"AllowedScopes": [ "openid", "profile", "API" ],
"RedirectUris": [ "http://localhost:4200/auth-callback" ],
"RequireConsent": false,
"RequireClientSecret": false
}
]
I get: System.InvalidOperationException: 'Type '' is not supported.' at startup
If I try to configure the client in code, and only keep the "Key" section in appsettings
services
.AddIdentityServer(options =>
{
options.Cors.CorsPolicyName = _CorsPolicyName;
})
.AddInMemoryClients(new IdentityServer4.Models.Client[] {
new IdentityServer4.Models.Client
{
ClientId = "dev-client",
ClientName = "JavaScript Client",
ClientUri = "http://localhost:4200",
AllowedGrantTypes = { IdentityModel.OidcConstants.GrantTypes.Implicit },
AllowAccessTokensViaBrowser = true,
RedirectUris = { "http://localhost:4200/auth-callback" },
PostLogoutRedirectUris = { "http://localhost:4200" },
AllowedCorsOrigins = { "http://localhost:4200" },
AllowedScopes =
{
IdentityServer4.IdentityServerConstants.StandardScopes.OpenId,
IdentityServer4.IdentityServerConstants.StandardScopes.Profile,
IdentityServer4.IdentityServerConstants.StandardScopes.Email,
"API"
}
}
})
I get: Unknown client or not enabled: dev-client.
Someone help me keep my sanity and point out my, most likely obvious, error.
ASP.NET Identity overrides the documented method for IdentityServer Clients configuration, expecting a dictionary of well-known values. You can bypass this by creating a section that is not named Clients and reading from that section explicitly. Additionally, AddApiAuthorization exposes the Clients collection on the ApiAuthorizationOptions, which can be used to add other clients:
.AddApiAuthorization<...>(options =>
{
options.Clients.AddRange(Configuration.GetSection("IdentityServer:OtherClients").Get<Client[]>());
});

ConfigureKestrel() conflict with appsettings

I have Kestrel section in appsettings.json and I also call ConfigureKestrel() in Program.cs. When I run the app, there is an error:
11:10:36 [Warning] () Overriding address(es) '"https://localhost:5003"'. Binding to endpoints defined in "UseKestrel()" instead.
11:10:36 [Fatal] () Unable to start Kestrel.
System.IO.IOException: Failed to bind to address https://[::]:5003: address already in use. ---> Microsoft.AspNetCore.Connections.AddressInUseException: Address already in use ---> System.Net.Sockets.SocketException: Address already in use
Here is my appsettings.json:
"Kestrel": {
"Endpoints": {
"HttpsInlineCertFile": {
"Url": "https://localhost:5003",
"Certificate": {
"Path": "/tmp/localhost.pfx",
"Password": "password"
}
},
"HttpsDefaultCert": {
"Url": "https://localhost:5003"
},
"Https": {
"Url": "https://*:5003",
"Certificate": {
"Path": "/tmp/localhost.pfx",
"Password": "password"
}
}
},
"Certificates": {
"Default": {
"Path": "/tmp/localhost.pfx",
"Password": "password"
}
}
},
Here is my ConfigureKestrel():
.ConfigureKestrel((context, options) =>
{
options.Listen(IPAddress.Any, 5003, listenOptions =>
{
listenOptions.UseHttps(o => o.SslProtocols = SslProtocols.Tls12);
listenOptions.UseConnectionLogging();
listenOptions.Protocols = HttpProtocols.Http1AndHttp2;
});
});
OR:
.ConfigureKestrel((context, options) =>
{
options.Configure(context.Configuration.GetSection("Kestrel"))
.Endpoint("Https", listenOptions =>
{
listenOptions.HttpsOptions.SslProtocols = SslProtocols.Tls12;
listenOptions.ListenOptions.UseConnectionLogging();
listenOptions.ListenOptions.Protocols = HttpProtocols.Http1AndHttp2;
});
});
So, which is which? I am confused. Can I do everything in appsettings.json?
Update: I have figured out how to configure other options in appsettings.json except 2: listenOptions.HttpsOptions.SslProtocols and UseConnectionLogging