Skip to content
This repository was archived by the owner on Jun 11, 2024. It is now read-only.
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
152 changes: 152 additions & 0 deletions browserup-proxy-rest-clients/build.gradle
Original file line number Diff line number Diff line change
@@ -0,0 +1,152 @@
/*
* Modifications Copyright (c) 2019 BrowserUp, Inc.
*/

plugins {
id 'java-library'
id 'groovy'
id "io.swagger.core.v3.swagger-gradle-plugin" version "2.1.6"
id 'org.openapi.generator' version '4.3.1'
}

ext {
jerseyVersion = '2.32'
}

resolve {
outputFileName = 'openapi'
outputFormat = 'YAML'
prettyPrint = 'TRUE'
openApiFile = file("src/main/resources/openapi-config.json")
classpath = sourceSets.main.runtimeClasspath
readerClass = "com.browserup.bup.rest.openapi.CustomOpenApiReader"
resourcePackages = ['com.browserup.bup.rest.resource']
outputPath = "$buildDir/openapi"
}

class Constants {
static String apiPackage = 'browserup'
static String modelPackage = 'browserup.model'
}

/*
https://github.com/OpenAPITools/openapi-generator/issues/3285
*/
class PythonClientPostProcessor {
String projectDir

void process() {
def clientDir = new File("$projectDir/build/openapi-clients/python")
clientDir.eachFileRecurse {
if (it.name.endsWith(".py")) {
processInitFile(it)
}
}
new File("${clientDir}/openapi_client/${Constants.apiPackage}/model/__init__.py") <<
new File("${clientDir}/openapi_client/${Constants.modelPackage}/__init__.py").text
}

private static void processInitFile(File initFile) {
initFile.text = initFile.text.replaceAll(
~/(from ${Constants.apiPackage}.default_api import)/,
"from openapi_client.${Constants.apiPackage}.default_api import"
)
}
}

class ClientInfo {
String language
Closure postProcessor
}

def clients = [
new ClientInfo(language: 'JavaScript'),
new ClientInfo(language: 'Ruby'),
new ClientInfo(
language: 'Python',
postProcessor: new PythonClientPostProcessor(projectDir: projectDir).&process)
] as ClientInfo[]

clients.each { client ->
def lang = client.language
def postProcessor = client.postProcessor

task "openApiGenerate${lang}Client"(type: org.openapitools.generator.gradle.plugin.tasks.GenerateTask) {
def language = lang.toLowerCase()
generatorName = language
inputSpec = "$buildDir/openapi/openapi.yaml".toString()
outputDir = "$buildDir/openapi-clients/$language/".toString()
apiPackage = Constants.apiPackage
modelPackage = Constants.modelPackage
invokerPackage = "browserup.invoker"
systemProperties = [
modelDocs: 'false'
]
skipValidateSpec = true
logToStderr = true
generateAliasAsModel = false
}
if (postProcessor) tasks.getByName("openApiGenerate${lang}Client").doLast(postProcessor)
}

test {
testLogging.showStandardStreams = true
}

task openApiGenerateClients(dependsOn: resolve) {
clients.each { c ->
dependsOn "openApiGenerate${c.language}Client"
}

doLast {
clients.each { client ->
def langName = client.language.toLowerCase()
delete "src/test/${langName}/client"
copy {
from "$buildDir/openapi-clients/${langName}/"
into "src/test/${langName}/client"
}
}

project.delete "$buildDir/openapi-clients"
}
}

archivesBaseName = 'browserup-proxy-rest-clients'

dependencies {
implementation project(':browserup-proxy-core')
implementation project(':browserup-proxy-rest')

testImplementation "org.glassfish.jersey.containers:jersey-container-servlet-core:${jerseyVersion}"
testImplementation "org.glassfish.jersey.media:jersey-media-json-jackson:${jerseyVersion}"
testImplementation "org.glassfish.jersey.inject:jersey-hk2:${jerseyVersion}"
testImplementation "org.glassfish.jersey.ext:jersey-bean-validation:${jerseyVersion}"

testImplementation project(':browserup-proxy-mitm')

testImplementation "com.google.inject:guice:$guiceVersion"
testImplementation "com.google.inject.extensions:guice-servlet:$guiceVersion"
testImplementation "com.google.inject.extensions:guice-multibindings:$guiceVersion"

testImplementation 'com.google.sitebricks:sitebricks:0.8.11'

testImplementation 'junit:junit:4.12'
testImplementation "org.apache.logging.log4j:log4j-api:${log4jVersion}"
testImplementation "org.apache.logging.log4j:log4j-core:${log4jVersion}"
testImplementation "org.apache.logging.log4j:log4j-slf4j-impl:${log4jVersion}"
testImplementation 'org.codehaus.groovy:groovy-all:2.5.7'
testImplementation 'org.codehaus.groovy.modules.http-builder:http-builder:0.7.2'
testImplementation 'org.hamcrest:hamcrest:2.1'
testImplementation 'org.hamcrest:hamcrest-library:2.1'
testImplementation 'org.mockito:mockito-core:3.0.0'
testImplementation 'org.seleniumhq.selenium:selenium-api:3.4.0'
testImplementation 'org.awaitility:awaitility:3.1.6'
testImplementation 'xyz.rogfam:littleproxy:2.0.0-beta-3'
testImplementation 'com.github.tomakehurst:wiremock-jre8:2.24.0'
testImplementation 'org.testcontainers:testcontainers:1.12.0'
}

openApiGenerateClients.mustRunAfter(resolve)

test.dependsOn(openApiGenerateClients)
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
{
"resourcePackages" : [
"com.browserup.bup.rest.resource"
],
"openapi" : "3.0.1",
"info": {
"version": "1.0",
"title": "BrowserUp Proxy API",
"description": "BrowserUp Proxy API",
"contact": {
"email": "hello@browserup.com"
},
"license": {
"name": "Apache 2.0",
"url": "http://www.apache.org/licenses/LICENSE-2.0.html"
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,192 @@
/*
* Modifications Copyright (c) 2019 BrowserUp, Inc.
*/

package com.browserup.bup

/*
* Modifications Copyright (c) 2019 BrowserUp, Inc.
*/

import com.browserup.bup.MitmProxyServer
import com.browserup.bup.proxy.MitmProxyManager
import com.browserup.bup.proxy.bricks.ProxyResource
import com.browserup.bup.proxy.guice.ConfigModule
import com.browserup.bup.proxy.guice.JettyModule
import com.browserup.bup.util.BrowserUpProxyUtil
import com.github.tomakehurst.wiremock.junit.WireMockRule
import com.google.inject.Guice
import com.google.inject.Injector
import com.google.inject.servlet.GuiceServletContextListener
import com.google.sitebricks.SitebricksModule
import groovyx.net.http.HTTPBuilder
import groovyx.net.http.Method
import org.apache.http.entity.ContentType
import org.awaitility.Awaitility
import org.eclipse.jetty.server.Server
import org.eclipse.jetty.servlet.ServletContextHandler
import org.junit.After
import org.junit.Before
import org.junit.Rule
import org.slf4j.Logger
import org.slf4j.LoggerFactory

import javax.servlet.ServletContextEvent
import java.util.concurrent.TimeUnit

import static com.github.tomakehurst.wiremock.client.WireMock.*
import static com.github.tomakehurst.wiremock.core.WireMockConfiguration.options
import static org.junit.Assert.assertEquals

abstract class WithRunningProxyRestTest {
private static final Logger LOG = LoggerFactory.getLogger(MitmProxyManager)

protected MitmProxyManager proxyManager
protected MitmProxyServer proxy
protected Server restServer

protected String[] getArgs() {
['--port', '0'] as String[]
}

abstract String getUrlPath();

String getFullUrlPath() {
return "/proxy/${proxy.port}/${urlPath}"
}

protected int mockServerPort
protected int mockServerHttpsPort

@Rule
public WireMockRule wireMockRule = new WireMockRule(options().port(0).httpsPort(0))

@Before
void setUp() throws Exception {
Injector injector = Guice.createInjector(new ConfigModule(args), new JettyModule(), new SitebricksModule() {
@Override
protected void configureSitebricks() {
scan(ProxyResource.class.getPackage())
}
})

proxyManager = injector.getInstance(MitmProxyManager)

LOG.debug("Starting BrowserUp Proxy version " + BrowserUpProxyUtil.versionString)

new Thread(new Runnable() {
@Override
void run() {
startRestServer(injector)
}
}).start()

LOG.debug("Waiting till BrowserUp Rest server is started")

Awaitility.await().atMost(10, TimeUnit.SECONDS).until({ -> restServer != null && restServer.isStarted() })

LOG.debug("BrowserUp Rest server is started successfully")

LOG.debug("Waiting till BrowserUp Proxy server is started")

proxy = proxyManager.create(0)

Awaitility.await().atMost(5, TimeUnit.SECONDS).until({ -> proxyManager.get().size() > 0 })

LOG.debug("BrowserUp Proxy server is started successfully")

mockServerPort = wireMockRule.port();
mockServerHttpsPort = wireMockRule.httpsPort();

waitForProxyServer()
}

def waitForProxyServer() {
Awaitility.await().atMost(5, TimeUnit.SECONDS).until({ ->
def successful = false
proxyRestServerClient.request(Method.GET, ContentType.TEXT_PLAIN) { req ->
uri.path = "/proxy"
response.success = { _, reader ->
successful = true
}
response.failure = { _, reader ->
successful = false
}
}
return successful
})
}

HTTPBuilder getTargetServerClient() {
def http = new HTTPBuilder("http://localhost:${mockServerPort}")
http.setProxy('localhost', proxy.port, 'http')
http
}

HTTPBuilder getProxyRestServerClient() {
new HTTPBuilder("http://localhost:${restServer.connectors[0].localPort}")
}

def sendGetToProxyServer(Closure configClosure) {
proxyRestServerClient.request(Method.GET, ContentType.WILDCARD, configClosure)
}

void requestToTargetServer(url, expectedResponse) {
targetServerClient.request(Method.GET, ContentType.TEXT_PLAIN) { req ->
uri.path = "/${url}"
response.success = { _, reader ->
assertEquals(expectedResponse, reader.text)
}
response.failure = { _, reader ->
assertEquals(expectedResponse, reader.text)
}
}
}

@After
void tearDown() throws Exception {
LOG.debug('Stopping proxy servers')
for (def proxyServer : proxyManager.get()) {
try {
proxyManager.delete(proxyServer.port)
} catch (Exception ex) {
LOG.error('Error while stopping proxy servers', ex)
}
}

if (restServer != null) {
LOG.debug('Stopping rest proxy server')
try {
restServer.stop()
} catch (Exception ex) {
LOG.error('Error while stopping rest proxy server', ex)
}
}
}

private void startRestServer(Injector injector) {
restServer = injector.getInstance(Server.class)
def contextListener = new GuiceServletContextListener() {
@Override
protected Injector getInjector() {
return injector
}
}
restServer.start()
contextListener.contextInitialized(
new ServletContextEvent((restServer.handler as ServletContextHandler).servletContext))
try {
restServer.join()
} catch (InterruptedException ignored) {
Thread.currentThread().interrupt()
}
}

protected void mockTargetServerResponse(String url, String responseBody, int delayMilliseconds=0) {
def response = aResponse().withStatus(200)
.withBody(responseBody)
.withHeader('Content-Type', 'text/plain')
.withFixedDelay(delayMilliseconds)
stubFor(get(urlEqualTo("/${url}")).willReturn(response))
}
}
Loading