Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Stricten, test, and bugfix http-server #170

Merged
merged 4 commits into from
Feb 16, 2024
Merged

Stricten, test, and bugfix http-server #170

merged 4 commits into from
Feb 16, 2024

Conversation

diehuxx
Copy link
Contributor

@diehuxx diehuxx commented Feb 9, 2024

All Changes

  1. Turn on typescript strict mode for the http-server package. Fix any bugs that strict mode reveals.
  2. Add many many tests which cover the request handlers completely, except for callback edge cases, which will be reworked in a follow up PR.
  3. Refactor how TbdexHttpServer calls the callbacks because the previous way actually did not work.
  4. Remove fakes.ts. Flesh out the "fake" implementations of ExchangesApi and OfferingsApi as fully usable InMemory implementations. See in-memory-exchanges-api.ts and in-memory-offerings-api.ts. These do not yet have 100% test coverage simply because this PR already adds ~1200 lines of tests; I'll add more tests in a follow up PR.

Changes to external API

Add fully fleshed out InMemoryExchangesApi and InMemoryOfferingsApi. These are used as defaults in TbdexHttpServer, but may be worth documenting in their own right.

Items TODO in follow up PRs

  1. Reach 100% test coverage of in-memory-exchanges-api.ts and in-memory-offerings-api.ts.
  2. Solidify the behavior of callback functions in the request handlers. Specifically, how callbacks can/cannot alter the HTTP response, how to handle if a callback throws an error, and what exactly should be passed to callbacks.

Copy link

changeset-bot bot commented Feb 9, 2024

⚠️ No Changeset found

Latest commit: 43c1390

Merging this PR will not cause a version bump for any packages. If these changes should not result in a new version, you're good to go. If these changes should result in a version bump, you need to add a changeset.

This PR includes no changesets

When changesets are added to this PR, you'll see the packages that this PR includes changesets for and the associated semver types

Click here to learn what changesets are, and how to add one.

Click here if you're a maintainer who wants to add a changeset to this PR

Base automatically changed from exchange-state-machine to main February 13, 2024 17:58
Copy link
Contributor

github-actions bot commented Feb 13, 2024

TBDocs Report

🛑 Errors: 0
⚠️ Warnings: 12

@tbdex/protocol

  • Project entry file: packages/protocol/src/main.ts

@tbdex/http-client

  • Project entry file: packages/http-client/src/main.ts
📄 File: packages/http-client/src/errors/request-error.ts
⚠️ extractor:ae-missing-release-tag: "RequestErrorParams" is part of the package's API, but it is missing a release tag (@alpha, @beta, @public, or @internal) #L1
⚠️ extractor:ae-undocumented: Missing documentation for "RequestErrorParams". #L1
⚠️ extractor:ae-undocumented: Missing documentation for "recipientDid". #L13
⚠️ extractor:ae-undocumented: Missing documentation for "url". #L14
📄 File: packages/http-client/src/errors/request-token-error.ts
⚠️ extractor:ae-missing-release-tag: "RequestTokenErrorParams" is part of the package's API, but it is missing a release tag (@alpha, @beta, @public, or @internal) #L3
⚠️ extractor:ae-undocumented: Missing documentation for "RequestTokenErrorParams". #L3
📄 File: packages/http-client/src/errors/response-error.ts
⚠️ extractor:ae-missing-release-tag: "ResponseErrorParams" is part of the package's API, but it is missing a release tag (@alpha, @beta, @public, or @internal) #L3
⚠️ extractor:ae-undocumented: Missing documentation for "ResponseErrorParams". #L3
⚠️ extractor:ae-undocumented: Missing documentation for "statusCode". #L15
⚠️ extractor:ae-undocumented: Missing documentation for "details". #L16
⚠️ extractor:ae-undocumented: Missing documentation for "recipientDid". #L17
⚠️ extractor:ae-undocumented: Missing documentation for "url". #L18

@tbdex/http-server

  • Project entry file: packages/http-server/src/main.ts

TBDocs Report Updated at 2024-02-16T22:41:57Z 43c1390

packages/http-server/tests/get-exchanges.spec.ts Dismissed Show dismissed Hide dismissed
packages/http-server/tests/get-exchanges.spec.ts Dismissed Show dismissed Hide dismissed
packages/http-server/src/http-server.ts Dismissed Show resolved Hide resolved
packages/http-server/src/http-server.ts Dismissed Show resolved Hide resolved
Copy link

codecov bot commented Feb 13, 2024

Codecov Report

Merging #170 (43c1390) into main (0702d91) will increase coverage by 3.49%.
The diff coverage is 88.09%.

Additional details and impacted files
@@            Coverage Diff             @@
##             main     #170      +/-   ##
==========================================
+ Coverage   88.99%   92.48%   +3.49%     
==========================================
  Files          36       37       +1     
  Lines        2825     2995     +170     
  Branches      262      321      +59     
==========================================
+ Hits         2514     2770     +256     
+ Misses        311      225      -86     
Components Coverage Δ
protocol 93.39% <100.00%> (+<0.01%) ⬆️
http-client 93.63% <ø> (ø)
http-server 89.49% <87.86%> (+18.34%) ⬆️

@diehuxx
Copy link
Contributor Author

diehuxx commented Feb 13, 2024

I'm deliberately not adding a changeset to this PR since I don't want to release a new version at this point. This PR adds a lot of tests and cleanup, but there is still more to come immediately afterward.

@diehuxx
Copy link
Contributor Author

diehuxx commented Feb 14, 2024

cc: @angiejones

@KendallWeihe
Copy link
Contributor

KendallWeihe commented Feb 15, 2024

This all makes sense to me (I only briefly glossed over the tests)

I'm deliberately not adding a changeset to this PR since I don't want to release a new version at this point. This PR adds a lot of tests and cleanup, but there is still more to come immediately afterward.

I think it may be good to list any breaking changes (changes to function signatures -- I call these "binary incompatibilities"), even if it's here in GitHub. But also, I'm not trying to promote unnecessary toil so I'm supportive of whatever we think is best. We have to manually cut releases so it's not like merging this will immediately break anything.

Great work!

@mistermoe
Copy link
Member

yooo @diehuxx

Refactor how TbdexHttpServer calls the callbacks because the previous way actually did not work.

what was the issue?

Copy link
Contributor

@jiyoontbd jiyoontbd left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nothing blocking, just a couple q's and comments! awesome work 🎉

packages/http-server/src/http-server.ts Dismissed Show resolved Hide resolved
offeringsApi: OfferingsApi
exchangesApi: ExchangesApi
}

export function createExchange(options: CreateExchangeOpts): RequestHandler {
export async function createExchange(req: Request, res: Response, options: CreateExchangeOpts): Promise<any> {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

could you explain the change from returning RequestHandler to Promise<any> ? i also am noticing that req and res are included as params as opposed to being abstracted away in the RequestHandler type definition

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I just pushed a commit changing the return type of this function to Promise<void>, explanation in this comment thread.

We're not longer using RequestHandler because the usage of this function has changed (see this comment for details). Previously, createExchange would return a function, which would be consumed by the express.js router like this:

    this.api.post('/exchanges/:exchangeId/rfq', createExchange({
      callback: this.callbacks['rfq'], offeringsApi, exchangesApi,
    }))

Now, createExchange does NOT return a function. It is consumed as a curried function by the express js router like this

    this.api.post('/exchanges/:exchangeId/rfq', (req: Request, res: Response) =>
      createExchange(req, res, {
        callback: this.callbacks['rfq'],
        offeringsApi,
        exchangesApi,
      })

return async function (request, response) {
const queryParams = request.query as GetOfferingsFilter
const offerings = await offeringsApi.getOfferings({ filter: queryParams || {} })
const filter: GetOfferingsFilter = {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

i like this explicit typing, but was request.query as GetOfferingsFilter not working as expected?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Using as in typescript is like telling the compiler "just trust me bro", so it's good to avoid it unless we as programmers are pretty confident. Since request.query could realistically be anything, it's better to select the specific fields we want and use filter: GetOfferingsFilter to help us remember which fields we need.

packages/http-server/tests/submit-close.spec.ts Outdated Show resolved Hide resolved
@diehuxx
Copy link
Contributor Author

diehuxx commented Feb 15, 2024

yooo @diehuxx

Refactor how TbdexHttpServer calls the callbacks because the previous way actually did not work.

what was the issue?

TL;DR functional programming is confusing.

Previously, in the listen method, we set the routes for the server like so:

this.api.get('/offerings', getOfferings({
      callback: this.callbacks['offerings'], offeringsApi
    }))

This calls this.callbacks['offerings'] at the time when server.listen() is called, which means that this.callbacks['offerings'] is always undefined because we haven't set our callbacks yet. What we actually want to do is get the callback when we handle an incoming message. I've done that like so:

    this.api.get('/offerings', (req, res) =>
      getOfferings(req, res, {
        callback: this.callbacks['offerings'],
        offeringsApi
      })
    )

The arrow method (req, res) => ... isn't called until the server handles an incoming request, which means this.callbacks['offerings'] isn't called until we handle a request. This allows us to do this:

const api = new TbdexHttpServer()
const server = api.listen()
api.onSubmitRfq(() => console.log('We received an RFQ'))
// When an RFQ is submitted, it prints
// "We received an RFQ"

// We can also overwrite the old callback
api.onSubmitRfq(() => console.log('TBDex is my best friend'))
// When an RFQ is submitted, it prints
// "TBDex is my best friend"

import { InMemoryExchangesApi } from '../src/in-memory-exchanges-api.js'
import { InMemoryOfferingsApi } from '../src/in-memory-offerings-api.js'
import { PortableDid } from '@web5/dids'
import Sinon from 'sinon'

describe('POST /exchanges/:exchangeId/rfq', () => {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

i feel like we have a race condition happening here as it fails occasionally but maybe im gaslighting myself

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Which test(s) specifically are failing? I haven't seen any flakiness but I can investigate if you let me know where to look.

Copy link
Contributor

@kirahsapong kirahsapong left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nyce!

* main:
  Version Packages (#167)
  Update web5/dids, web5/credentials, web5/crypto, web5/common to latest  (#177)
@diehuxx diehuxx merged commit ebefc54 into main Feb 16, 2024
15 of 17 checks passed
@diehuxx diehuxx deleted the ts-strict-http-server branch February 16, 2024 22:42
phoebe-lew added a commit that referenced this pull request Feb 20, 2024
* main:
  Stricten, test, and bugfix http-server (#170)
  Version Packages (#167)
  Update web5/dids, web5/credentials, web5/crypto, web5/common to latest  (#177)
  Add exchange state machine (#168)
  Stricten http-client (#169)
  Make `pfiDid` required property in `TbdexHttpServer` (#166)
diehuxx added a commit that referenced this pull request Feb 20, 2024
* main:
  Add external_id field (#163)
  Stricten, test, and bugfix http-server (#170)
  Version Packages (#167)
  Update web5/dids, web5/credentials, web5/crypto, web5/common to latest  (#177)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

5 participants