1
0
mirror of synced 2026-08-05 23:16:54 +00:00

feat: support http credentials

This commit is contained in:
Yury Semikhatsky
2020-10-02 11:41:16 -07:00
parent e036a1468c
commit b10a55895e
5 changed files with 62 additions and 8 deletions
@@ -415,7 +415,9 @@ public class FrameImpl extends ChannelOwner implements Frame {
@Override
public String title() {
return null;
JsonElement json = sendMessage("title", new JsonObject());
System.out.println(new Gson().toJson(json));
return json.getAsJsonObject().get("value").getAsString();
}
@Override
@@ -358,7 +358,7 @@ public class PageImpl extends ChannelOwner implements Page {
@Override
public String title() {
return null;
return mainFrame.title();
}
@Override
@@ -38,7 +38,7 @@ public class PlaywrightImpl extends ChannelOwner implements Playwright {
System.out.println("driver = " + driver.getCanonicalPath());
ProcessBuilder pb = new ProcessBuilder("node", driver.getCanonicalPath());
pb.redirectError(ProcessBuilder.Redirect.INHERIT);
// pb.environment().put("DEBUG", "pw:pro*");
// pb.environment().put("DEBUG", "pw:pro*");
Process p = pb.start();
Connection connection = new Connection(p.getInputStream(), p.getOutputStream());
PlaywrightImpl playwright = (PlaywrightImpl)connection.waitForObjectWithKnownName("Playwright");
@@ -28,7 +28,6 @@ import java.util.*;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.Future;
import static java.util.Collections.checkedCollection;
import static java.util.Collections.singletonList;
public class Server implements HttpHandler {
@@ -43,6 +42,17 @@ public class Server implements HttpHandler {
private final File resourcesDir;
private final Map<String, CompletableFuture<Request>> requestSubscribers = Collections.synchronizedMap(new HashMap<>());
private final Map<String, Auth> auths = Collections.synchronizedMap(new HashMap<>());
private static class Auth {
public final String user;
public final String password;
private Auth(String user, String password) {
this.user = user;
this.password = password;
}
}
Server(int port) throws IOException {
PORT = port;
@@ -63,9 +73,12 @@ public class Server implements HttpHandler {
server.stop(0);
}
void setAuth(String path, String user, String password) {
auths.put(path, new Auth(user, password));
}
public static class Request {
// TODO: make a copy to ensure thread safety
// TODO: make a copy to ensure thread safety?
public final Headers headers;
public Request(Headers headers) {
@@ -85,6 +98,31 @@ public class Server implements HttpHandler {
@Override
public void handle(HttpExchange exchange) throws IOException {
String path = exchange.getRequestURI().getPath();
if (auths.containsKey(path)) {
List<String> header = exchange.getRequestHeaders().get("authorization");
boolean authorized = false;
if (header != null) {
String v = header.get(0);
String[] splits = v.split(" ");
if (splits.length == 2) {
String credentials = new String(Base64.getDecoder().decode(splits[1]));
Auth auth = auths.get(path);
authorized = credentials.equals(auth.user + ":" + auth.password);
}
}
if (!authorized) {
exchange.getResponseHeaders().put("WWW-Authenticate", Arrays.asList("Basic realm=\"Secure Area\""));
exchange.sendResponseHeaders(401, 0);
try (Writer writer = new OutputStreamWriter(exchange.getResponseBody())) {
writer.write("HTTP Error 401 Unauthorized: Access is denied");
// TODO: notify subscriber?
exchange.getResponseBody().close();
}
return;
}
}
File file = new File(resourcesDir, path.substring(1));
exchange.getResponseHeaders().put("Content-Type", singletonList(mimeType(file)));
try (FileInputStream input = new FileInputStream(file)) {
@@ -26,6 +26,7 @@ import java.util.Map;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.Future;
import static com.microsoft.playwright.Page.LoadState.DOMCONTENTLOADED;
import static org.junit.jupiter.api.Assertions.*;
public class TestPopup {
@@ -81,7 +82,7 @@ public class TestPopup {
Deferred<Page> popupPromise = context.waitForPage();
page.click("a");
Page popup = popupPromise.get();
popup.waitForLoadState(Page.LoadState.DOMCONTENTLOADED);
popup.waitForLoadState(DOMCONTENTLOADED);
String userAgent = (String) popup.evaluate("() => window['initialUserAgent']");
Server.Request request = requestPromise.get();
context.close();
@@ -100,7 +101,6 @@ public class TestPopup {
route.continue_();
intercepted[0] = true;
});
Deferred<Page> popup = context.waitForPage();
page.click("a");
popup.get();
@@ -111,7 +111,7 @@ public class TestPopup {
@Test
void should_inherit_extra_headers_from_browser_context() throws ExecutionException, InterruptedException {
Map<String, String> headers = new HashMap<String, String>();
Map<String, String> headers = new HashMap<>();
headers.put("foo", "bar");
BrowserContext context = browser.newContext(new Browser.NewContextOptions().withExtraHTTPHeaders(headers));
Page page = context.newPage();
@@ -136,4 +136,18 @@ public class TestPopup {
context.close();
assertFalse(online);
}
@Test
void should_inherit_http_credentials_from_browser_context() {
server.setAuth("/title.html", "user", "pass");
BrowserContext context = browser.newContext(new Browser.NewContextOptions()
.setHttpCredentials().withUsername("user").withPassword("pass").done());
Page page = context.newPage();
page.navigate(server.EMPTY_PAGE);
Deferred<Page> popup = page.waitForPopup();
page.evaluate("url => window['_popup'] = window.open(url)", server.PREFIX + "/title.html");
popup.get().waitForLoadState(DOMCONTENTLOADED);
assertEquals("Woof-Woof", popup.get().title());
context.close();
}
}