-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Make more customisable via pipes (e.g. SHA sum, gunzip, etc)
- Loading branch information
1 parent
9b880ae
commit 9b956cc
Showing
10 changed files
with
228 additions
and
75 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,2 +1,3 @@ | ||
docker/static-files/10MB.bin* | ||
docker/static-files/100MB.bin* | ||
target/ |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,6 +1,9 @@ | ||
FROM nginx:stable | ||
|
||
COPY ./10MB.bin /var/www/10MB.bin | ||
COPY ./10MB.bin.gz /var/www/10MB.bin.gz | ||
COPY ./100MB.bin /var/www/100MB.bin | ||
COPY ./100MB.bin.gz /var/www/100MB.bin.gz | ||
COPY ./nginx.conf /etc/nginx/conf.d/default.conf | ||
|
||
CMD ["nginx", "-g", "daemon off;"] |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,47 @@ | ||
package vdx.fetchfile | ||
|
||
import cats.Applicative | ||
import cats.effect.Concurrent | ||
import cats.effect.concurrent.Ref | ||
import cats.instances.string._ | ||
import cats.kernel.Semigroup | ||
import cats.syntax.eq._ | ||
import cats.syntax.functor._ | ||
import cats.syntax.semigroup._ | ||
import fs2.{Pipe, RaiseThrowable, Stream} | ||
|
||
object Pipes { | ||
|
||
/** | ||
* An fs2 Pipe that collects the SHA-256 sum of the stream as a | ||
* series of bytes. The result container can be anything that has an | ||
* Applicative and a Semigroup instance. | ||
* | ||
* @tparam F The Concurrent effect of the Stream | ||
* @tparam G The type of the contianer that holds the collected bytes | ||
* @param shaRef The ref that holds the bytes of the SHA sum | ||
* @param S The implicit Semigroup instance of G[Byte] | ||
*/ | ||
def collectSHA256[F[_]: Concurrent, G[_]: Applicative]( | ||
shaRef: Ref[F, G[Byte]] | ||
)(implicit S: Semigroup[G[Byte]]): Pipe[F, Byte, Byte] = | ||
_.observe(_.through(fs2.hash.sha256).evalTap(byte => shaRef.update(_ |+| Applicative[G].pure(byte))).void) | ||
|
||
/** | ||
* An fs2 Pipe that compares the stream's SHA-256 sum to the given ` | ||
* @tparam F | ||
* @param expectedSHA | ||
* @param C | ||
*/ | ||
def ensureSHA256[F[_]: RaiseThrowable](expectedSHA: String)(implicit C: Stream.Compiler[F, F]): Pipe[F, Byte, Unit] = | ||
stream => | ||
Stream | ||
.eval( | ||
stream.through(fs2.hash.sha256).compile.toVector | ||
) | ||
.map(_.map("%02x".format(_)).mkString) | ||
.flatMap { hash => | ||
if (hash === expectedSHA.toLowerCase()) Stream.emit(()).covary[F] | ||
else Stream.raiseError(new Exception(s"Sha256 sum doesn't match (expected: $expectedSHA, got: $hash)")) | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,88 @@ | ||
package vdx.fetchfile | ||
|
||
import cats.effect.ContextShift | ||
import cats.effect.IO | ||
import cats.effect.concurrent.Ref | ||
import cats.instances.list._ | ||
import fs2.Stream | ||
import org.scalacheck.Arbitrary | ||
import org.scalacheck.Gen | ||
import org.scalacheck.Prop | ||
import org.scalatest.matchers.should.Matchers | ||
import org.scalatest.wordspec.AnyWordSpec | ||
import org.scalatestplus.scalacheck.Checkers | ||
import org.typelevel.claimant.Claim | ||
|
||
import scala.concurrent.ExecutionContext | ||
|
||
import java.security.MessageDigest | ||
|
||
@SuppressWarnings(Array("scalafix:DisableSyntax.==")) | ||
class PipesSpec extends AnyWordSpec with Matchers with TestHttpClient with Checkers { | ||
implicit val cs: ContextShift[IO] = IO.contextShift(ExecutionContext.global) | ||
|
||
val testText = "This is a test text" | ||
val expectedShaSum = "c62968ebcd6b7c706a8ac082db862682fa8be407106cb7eaa050c713a4e969d7" | ||
|
||
val byteArray: Gen[Array[Byte]] = Gen.listOf(Arbitrary.arbByte.arbitrary).map(_.toArray) | ||
|
||
"ensureSHA256" should { | ||
"do nothing when the given shaSum is correct" in { | ||
check( | ||
Prop.forAllNoShrink(byteArray) { bytes => | ||
Stream | ||
.emits(bytes) | ||
.covary[IO] | ||
.through(Pipes.ensureSHA256(calcHash("SHA-256", bytes))) | ||
.compile | ||
.drain | ||
.attempt | ||
.unsafeRunSync() | ||
.isRight | ||
} | ||
) | ||
} | ||
|
||
"fail the stream when the given shasum is not correct" in { | ||
check( | ||
Prop.forAllNoShrink(byteArray) { bytes => | ||
Stream | ||
.emits(bytes) | ||
.covary[IO] | ||
.through(Pipes.ensureSHA256("some-wrong-sha")) | ||
.compile | ||
.drain | ||
.attempt | ||
.unsafeRunSync() | ||
.isLeft | ||
} | ||
) | ||
} | ||
} | ||
|
||
"collectSHA256" should { | ||
"collect the shasum without modifying the stream" in { | ||
check( | ||
Prop.forAllNoShrink(byteArray) { bytes => | ||
(for { | ||
ref <- Ref.of[IO, List[Byte]](List.empty) | ||
result <- Stream.emits(bytes).covary[IO].through(Pipes.collectSHA256(ref)).compile.toList | ||
collected <- ref.get | ||
} yield { | ||
Claim( | ||
result == bytes.toList && | ||
collected.map("%02x".format(_)).mkString == calcHash("SHA-256", bytes) | ||
) | ||
}).unsafeRunSync() | ||
} | ||
) | ||
} | ||
} | ||
|
||
def calcHash(algo: String, bytes: Array[Byte]): String = | ||
MessageDigest | ||
.getInstance(algo) | ||
.digest(bytes) | ||
.map("%02x".format(_)) | ||
.mkString | ||
} |
Oops, something went wrong.